DIRECTORY AMBridge USING [GetWorld, IsRemote, nilRemoteFrameHandle, nilRemoteGlobalFrameHandle, RemoteFHFromTV, RemoteFrameHandle, RemoteGFHFromTV, RemoteGlobalFrameHandle, RemotePD, RemoteSED, TVForProc, TVForRemoteFrame, TVForRemoteGFHReferent, TVForRemoteProc, TVForRemoteSignal, TVForSignal, TVToCardinal, TVToRemoteProc,TVToRemoteSignal, WordSequence, WordSequenceRecord], AMProcessBasic USING[ReturnLink], AMTypes USING [Domain, Error, Index, IndexToTV, Range, Size, TV, TVStatus, TVType, TypeClass, TypedVariable, UnderType], BrandXSymbolDefs USING [SymbolTableBase, rootBodyIndex, BodyIndex, nullBodyIndex, outerContextLevel], BrandYSymbolDefs USING [SymbolTableBase, rootBodyIndex, BodyIndex, nullBodyIndex, outerContextLevel], DebuggerSwap USING[CallDebugger], LoadState USING[GlobalFrameToType, local, Acquire, Release], PrincOps USING [BytePC, ControlLink, CSegPrefix, EPRange, Frame, FrameHandle, GlobalFrame, GlobalFrameHandle, localbase, MaxNGfi, NullLink, ProcDesc, SignalDesc, StateVector, UnboundLink, SD, sSignal], PrincOpsUtils USING[GlobalFrame, Codebase], RemotePrincOpsUtils USING[RemoteGlobalFrame], Rope USING[ROPE], RTSymbolDefs USING [BlockContextLevel, BodyIndex, CallableBodyIndex, nullBodyIndex, SymbolConstructorIndex, SymbolIdIndex, SymbolIndex, SymbolTableBase], RTSymbolOps USING [AcquireType, BodyLevel, BodyType, CallableBodyEntryIndex, CallableBTI, ISEConstant, ISEImmutable, ISEType, IsRootBTI, IsTypeSEI, NullBTI, NullSEI, ParentBody, RootBodyType, SEUnderType], RTSymbols USING[AcquireSTBFromGFH, ReleaseSTB], RTTypesPrivate USING [BuildRecordFieldDescriptor, FieldDescriptor, GetIdConstantValue, GFHToName, RecordComponentISEI, TypedVariableRec, UnwindIndirectProcDesc], RTTypesRemotePrivate USING [AcquireBTIFromRemoteFH, AcquireSTBFromRemoteGFH, GetRemoteEp, GetRemoteFrameHeader, GetRemoteGFHeader, IsRemoteCatchFrame, RemoteGFHToName, RemoteSignalValues], SafeStorage USING[Type, nullType, fhType, gfhType], WorldVM USING[CurrentIncarnation, Long, ShortAddress, World, LocalWorld]; RTTypedFramesImpl: PROGRAM IMPORTS AMProcessBasic, AMTypes, LoadState, RTSymbolOps, RTSymbols, AMBridge, PrincOpsUtils, RemotePrincOpsUtils, RTTypesPrivate, RTTypesRemotePrivate, DebuggerSwap, WorldVM EXPORTS AMTypes, AMBridge, RTTypesPrivate = BEGIN OPEN AMBridge, AMTypes, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, RemotePrincOpsUtils, Rope, RTSymbolDefs, RTSymbolOps, RTSymbols, SafeStorage, RTTypesPrivate, RTTypesRemotePrivate, WorldVM; EVRange: TYPE = [0..4*PrincOps.EPRange); sigGF: PrincOps.GlobalFrameHandle = LOOPHOLE[ PrincOpsUtils.GlobalFrame[LOOPHOLE[PrincOps.SD[PrincOps.sSignal], PrincOps.ProcDesc]]]; TVToSignal: PUBLIC PROC[tv: TypedVariable] RETURNS[ERROR ANY RETURNS ANY] = { SELECT TypeClass[UnderType[TVType[tv]]] FROM signal, error => NULL; nil => RETURN[LOOPHOLE[PrincOps.UnboundLink, ERROR ANY RETURNS ANY]]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; RETURN[LOOPHOLE[TVToCardinal[tv], ERROR ANY RETURNS ANY]]; }; TVForFrame: PUBLIC PROC[ fh: PrincOps.FrameHandle, evalStack: POINTER TO PrincOps.StateVector _ NIL, return: BOOL _ FALSE, contextPC: BOOL _ FALSE] RETURNS[ans: TV _ NIL] = { bti: BodyIndex; isCatchFrame: BOOLEAN _ FALSE; IF fh = NIL THEN RETURN[NIL]; [isCatchFrame, bti] _ AcquireBTIFromFH[fh, contextPC ! Error => IF reason = noSymbols THEN {bti _ nullBodyIndex; CONTINUE}]; RETURN[NEW[TypedVariableRec _ [referentType: [fhType], head: [fh[fh: fh, evalStack: evalStack, bti: bti, isCatchFrame: isCatchFrame, return: return, contextPC: contextPC]], status: mutable, field: entire[] ]]]; }; FHFromTV: PUBLIC PROC[tv: TypedVariable] RETURNS[PrincOps.FrameHandle] = { IF tv = NIL THEN RETURN[NIL]; WITH tv SELECT FROM tr: REF TypedVariableRec => WITH tfh: tr.head SELECT FROM fh => RETURN[tfh.fh]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; }; TVForGFHReferent: PUBLIC PROC[gfh: PrincOps.GlobalFrameHandle] RETURNS[TypedVariable] = { IF gfh = NIL THEN RETURN[NIL]; RETURN[NEW[TypedVariableRec _ [referentType: [gfhType], head: [gfh[gfh: gfh]], status: mutable, field: entire[]]]]; }; GFHFromTV: PUBLIC PROC[tv: TypedVariable] RETURNS[PrincOps.GlobalFrameHandle] = { IF tv = NIL THEN RETURN[NIL]; WITH tv SELECT FROM tr: REF TypedVariableRec => WITH tgfh: tr.head SELECT FROM gfh => RETURN[tgfh.gfh]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; ENDCASE => ERROR; }; GlobalParent: PUBLIC SAFE PROC[tv: TypedVariable--transfer or local frame--] RETURNS[TypedVariable--globalFrame--] = TRUSTED { IF IsRemote[tv] THEN { type: Type = TVType[tv]; gfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; SELECT TypeClass[UnderType[type]] FROM localFrame => { fh: RemoteFrameHandle = RemoteFHFromTV[tv]; IF fh.fh = 0 THEN RETURN[NIL]; gfh _ [world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[GetRemoteFrameHeader[fh].accesslink, WorldVM.ShortAddress]]; }; program, procedure => { pd: RemotePD = TVToRemoteProc[tv]; IF pd.pd = PrincOps.NullLink THEN RETURN[NIL]; gfh _ [world: pd.world, worldIncarnation: CurrentIncarnation[pd.world], gfh: LOOPHOLE[RemoteGlobalFrame[pd.world, pd.pd], WorldVM.ShortAddress]]; }; signal, error => { sed: RemoteSED = TVToRemoteSignal[tv]; IF sed.sed = PrincOps.NullLink OR LOOPHOLE[sed.sed, CARDINAL] = 177777B OR LOOPHOLE[sed.sed, CARDINAL] = LOOPHOLE[UNWIND, CARDINAL] OR LOOPHOLE[sed.sed, CARDINAL] = LOOPHOLE[ABORTED, CARDINAL] THEN RETURN[NIL]; gfh _ [world: sed.world, worldIncarnation: CurrentIncarnation[sed.world], gfh: LOOPHOLE[RemoteGlobalFrame[sed.world, sed.sed], WorldVM.ShortAddress]]; }; nil => RETURN[NIL]; ENDCASE => ERROR Error[reason: typeFault, type: type]; RETURN[TVForRemoteGFHReferent[gfh]]; } ELSE { -- local case type: Type = TVType[tv]; gfh: PrincOps.GlobalFrameHandle; SELECT TypeClass[UnderType[type]] FROM localFrame => { fh: PrincOps.FrameHandle = FHFromTV[tv]; IF fh = NIL THEN RETURN[NIL]; gfh _ fh.accesslink; }; signal, error => { sed: PrincOps.ProcDesc = LOOPHOLE[TVToSignal[tv], PrincOps.ProcDesc]; IF sed = PrincOps.NullLink OR LOOPHOLE[sed, CARDINAL] = 177777B OR LOOPHOLE[sed, CARDINAL] = LOOPHOLE[UNWIND, CARDINAL] OR LOOPHOLE[sed, CARDINAL] = LOOPHOLE[ABORTED, CARDINAL] THEN RETURN[NIL]; gfh _ LOOPHOLE[PrincOpsUtils.GlobalFrame[sed], PrincOps.GlobalFrameHandle]; }; program, procedure => { pd: PrincOps.ProcDesc = UnwindIndirectProcDesc[LOOPHOLE[TVToCardinal[tv], PrincOps.ControlLink]]; IF pd = PrincOps.NullLink THEN RETURN[NIL]; gfh _ LOOPHOLE[PrincOpsUtils.GlobalFrame[pd], PrincOps.GlobalFrameHandle]; }; nil => RETURN[NIL]; ENDCASE => ERROR Error[reason: typeFault, type: type]; RETURN[TVForGFHReferent[gfh]]; }; }; -- end GlobalParent ContextPC: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS[ans: PrincOps.BytePC] = TRUSTED { WITH th: NARROW[tv, REF TypedVariableRec].head SELECT FROM remoteFH => ans _ [GetRemoteFrameHeader[RemoteFHFromTV[tv]].pc - (IF th.contextPC THEN 0 ELSE 1)]; fh => ans _ [th.fh.pc - (IF th.contextPC THEN 0 ELSE 1)]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; }; IsStarted: PUBLIC SAFE PROC[tv: TypedVariable--globalFrame--] RETURNS[BOOL] = TRUSTED { rtr: REF TypedVariableRec _ NARROW[tv]; IF IsRemote[tv] THEN { rgfh: REF PrincOps.GlobalFrame = GetRemoteGFHeader[RemoteGFHFromTV[tv]]; RETURN[(NOT rgfh.code.out) OR rgfh.started]; } ELSE WITH th: rtr.head SELECT FROM gfh => RETURN[(NOT th.gfh.code.out) OR th.gfh.started]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; }; IsCopied: PUBLIC SAFE PROC[tv: TypedVariable--globalFrame--] RETURNS[BOOL] = TRUSTED { rtr: REF TypedVariableRec _ NARROW[tv]; IF IsRemote[tv] THEN { rgfh: REF PrincOps.GlobalFrame = GetRemoteGFHeader[RemoteGFHFromTV[tv]]; RETURN[rgfh.copied]; } ELSE WITH th: rtr.head SELECT FROM gfh => RETURN[th.gfh.copied]; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; }; Procedure: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS [TypedVariable--procedure--] = TRUSTED { IF IsRemote[tv] THEN { stb: SymbolTableBase; rtr: REF TypedVariableRec; bti: BodyIndex; fh: RemoteFrameHandle _ nilRemoteFrameHandle; IF tv = NIL THEN RETURN[NIL]; rtr _ NARROW[tv]; WITH th: rtr.head SELECT FROM remoteFH => IF th.isCatchFrame THEN bti _ nullBodyIndex ELSE { bti _ th.bti; IF NullBTI[bti] -- last time there were no symbols for this turkey THEN { name: ROPE; fh _ RemoteFHFromTV[tv]; bti _ th.bti _ AcquireBTIFromRemoteFH[fh, th.contextPC]; IF NOT NullBTI[th.bti] THEN { [th.isCatchFrame, th.bti] _ IsRemoteCatchFrame[fh, bti]; bti _ th.bti; IF th.isCatchFrame THEN bti _ nullBodyIndex; } ELSE { name _ RemoteGFHToName [[world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[GetRemoteFrameHeader[fh].accesslink, WorldVM.ShortAddress]]]; ERROR AMTypes.Error[reason: noSymbols, msg: name]; }; }; }; ENDCASE => bti _ nullBodyIndex; IF NullBTI[bti] THEN ERROR Error[reason: typeFault, type: TVType[tv]]; fh _ RemoteFHFromTV[tv]; IF fh.fh = 0 THEN RETURN[NIL]; stb _ AcquireSTBFromRemoteGFH [[world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[GetRemoteFrameHeader[fh].accesslink, WorldVM.ShortAddress]]]; FOR bti _ bti, ParentBody[stb, bti] UNTIL NullBTI[bti] DO IF CallableBTI[stb, bti] THEN { sppd: PrincOps.ProcDesc _ LOOPHOLE[PrincOps.UnboundLink, PrincOps.ProcDesc]; entryIndex: [0..PrincOps.EPRange*PrincOps.MaxNGfi) _ CallableBodyEntryIndex[stb, LOOPHOLE[bti, CallableBodyIndex]]; IF entryIndex = 0 THEN ERROR Error[reason: typeFault, type: TVType[tv]]; sppd.gfi _ GetRemoteGFHeader [[world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[GetRemoteFrameHeader[fh].accesslink, WorldVM.ShortAddress] ]].gfi + entryIndex/PrincOps.EPRange; sppd.ep _ entryIndex MOD PrincOps.EPRange; ReleaseSTB[stb]; RETURN[TVForRemoteProc[[fh.world, CurrentIncarnation[fh.world], sppd]]]; }; ENDLOOP; ReleaseSTB[stb]; RETURN[NIL]; } ELSE {-- non-remote localFrame TV arg to Procedure stb: SymbolTableBase; rtr: REF TypedVariableRec; bti: BodyIndex; fh: PrincOps.FrameHandle; IF tv = NIL THEN RETURN[NIL]; rtr _ NARROW[tv]; WITH th: rtr.head SELECT FROM fh => IF th.isCatchFrame THEN ERROR Error[reason: typeFault, type: TVType[tv]] ELSE { bti _ th.bti; IF NullBTI[bti] -- no symbols for this localFrame TV THEN { fh _ FHFromTV[tv]; bti _ th.bti _ AcquireBTIFromFH[fh, th.contextPC ! ANY => CONTINUE].bti; IF NOT NullBTI[th.bti] THEN { [th.isCatchFrame, th.bti] _ IsCatchFrame[fh, bti]; bti _ th.bti; IF th.isCatchFrame THEN ERROR Error[reason: typeFault, type: TVType[tv]]; } ELSE ERROR AMTypes.Error[reason: noSymbols, msg: GFHToName[th.fh.accesslink]]; }; }; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; fh _ FHFromTV[tv]; IF fh = NIL THEN RETURN[NIL]; stb _ AcquireSTBFromGFH[fh.accesslink]; FOR bti _ bti, ParentBody[stb, bti] UNTIL NullBTI[bti] DO IF CallableBTI[stb, bti] THEN { sppd: PrincOps.ProcDesc _ LOOPHOLE[PrincOps.UnboundLink, PrincOps.ProcDesc]; entryIndex: [0..PrincOps.EPRange*PrincOps.MaxNGfi) _ CallableBodyEntryIndex[stb, LOOPHOLE[bti, CallableBodyIndex]]; sppd.gfi _ fh.accesslink.gfi + entryIndex/PrincOps.EPRange; sppd.ep _ entryIndex MOD PrincOps.EPRange; ReleaseSTB[stb]; RETURN[TVForProc[LOOPHOLE[sppd, PROC ANY RETURNS ANY]]]; }; ENDLOOP; ReleaseSTB[stb]; ERROR; }; }; -- end Procedure Signal: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS[ans: TypedVariable--signal descriptor--] = TRUSTED { IF IsRemote[tv] THEN { world: World; sed: PrincOps.SignalDesc; [world: world, signal: sed] _ RemoteSignalValues[tv]; ans _ TVForRemoteSignal [[world: world, worldIncarnation: CurrentIncarnation[world], sed: sed]] } ELSE ans _ TVForSignal[LOOPHOLE[RemoteSignalValues[tv].signal, ERROR ANY RETURNS ANY]]}; Argument: PUBLIC SAFE PROC[tv: TypedVariable--local or catch Frame--, index: Index] RETURNS[TypedVariable] = TRUSTED {RETURN[ArgOrResult[tv, index, Domain]]}; Result: PUBLIC SAFE PROC[tv: TypedVariable--local or catch Frame--, index: Index] RETURNS[TypedVariable] = TRUSTED {RETURN[ArgOrResult[tv, index, Range]]}; ArgOrResult: PROC[ tv: TypedVariable--local or catch Frame--, index: Index, domainOrRange: PROC[Type] RETURNS [Type] ] RETURNS[TypedVariable] = { type: Type; catch: BOOL; message: UNSPECIFIED; world: World; argsTV: REF TypedVariableRec; tvr: REF TypedVariableRec; offset: INTEGER _ 0; GetSignalOrProcType: PROC[tv: TypedVariable] RETURNS [type: Type _ nullType, catch: BOOLEAN _ FALSE] = { rtr: REF TypedVariableRec _ NARROW[tv]; WITH th: rtr.head SELECT FROM fh => { catch _ th.isCatchFrame; type _ TVType[IF catch THEN Signal[tv] ELSE Procedure[tv]]; }; remoteFH => { catch _ th.isCatchFrame; type _ TVType[IF catch THEN Signal[tv] ELSE Procedure[tv]]; }; ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]; }; IF tv = NIL THEN ERROR Error[reason: typeFault, type: nullType]; tvr _ NARROW[tv]; [type, catch] _ GetSignalOrProcType[tv]; IF type = nullType THEN ERROR Error[reason: badIndex]; type _ domainOrRange[type]; IF type = nullType THEN ERROR Error[reason: badIndex]; WITH tvh: tvr.head SELECT FROM fh, remoteFH => NULL; ENDCASE => ERROR Error[reason: typeFault, type: type]; IF ~catch OR domainOrRange = Range THEN {-- find the specified element in the frame, create a TV for it BuildEmbeddedTV: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] = { sei: SymbolIndex = ISEType[stb, isei]; csei: SymbolConstructorIndex _ SEUnderType[stb, sei]; bitsForType: LONG CARDINAL _ (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.BitsForType[NARROW[csei, SymbolConstructorIndex.x].e], t: SymbolTableBase.y => t.e.BitsForType[NARROW[csei, SymbolConstructorIndex.x].e], ENDCASE => ERROR); -- bits for the value in the field fieldBits: CARDINAL _ (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.seb[NARROW[isei, SymbolIdIndex.x].e].idInfo, t: SymbolTableBase.y => t.e.seb[NARROW[isei, SymbolIdIndex.x].e].idInfo, ENDCASE => ERROR); -- bits for the field fieldBitOffset: CARDINAL _ (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.seb[NARROW[isei, SymbolIdIndex.x].e].idValue, t: SymbolTableBase.y => t.e.seb[NARROW[isei, SymbolIdIndex.x].e].idValue, ENDCASE => ERROR); cType: Type _ AcquireType[stb, sei]; IF ISEConstant[stb, isei] THEN { IF IsRemote[tv] AND IsTypeSEI[ISEType[stb, isei]] THEN argsTV _ NEW[TypedVariableRec _ [referentType: [cType], head: [constant[]], -- type code is valid in local world status: const, field: constant[value: GetIdConstantValue[tv, stb, isei]]]] ELSE -- either a constant component of a local tv or not a type constant argsTV _ NEW[TypedVariableRec _ [referentType: [cType], head: (WITH tv SELECT FROM tr: REF TypedVariableRec => tr.head, ENDCASE => ERROR), status: const, field: constant[value: GetIdConstantValue[tv, stb, isei]]]]; } ELSE argsTV _ NEW[TypedVariableRec _ [referentType: [cType], head: (WITH tv SELECT FROM tr:REF TypedVariableRec => tr.head, ENDCASE => ERROR), status: (IF ISEImmutable[stb, isei] THEN readOnly ELSE TVStatus[tv]), field: embedded[ fd: BuildRecordFieldDescriptor[tv, fieldBitOffset, fieldBits, bitsForType]]]]; }; -- END BuildEmbeddedTV RTTypesPrivate.RecordComponentISEI[UnderType[type], index, BuildEmbeddedTV]; RETURN[argsTV]; }; -- END ~catch OR domainOrRange = Range [world: world, message: message] _ RemoteSignalValues[tv]; IF Size[type] = 1 THEN { ws: WordSequence = NEW[WordSequenceRecord[1]]; ws[0] _ LOOPHOLE[message, CARDINAL]; argsTV _ NEW[TypedVariableRec _ [referentType: [type], head: tvr.head, status: const, field: constant[value: ws]]] } ELSE IF IsRemote[tv] THEN argsTV _ NEW[TypedVariableRec _ [referentType: [type], head: [remotePointer [remotePointer: [world: world, worldIncarnation: CurrentIncarnation[world], ptr: Long[world: world, addr: message]]]], status: readOnly, field: entire[]]] ELSE argsTV _ NEW[TypedVariableRec _ [referentType: [type], head: [pointer[ptr: LONG[LOOPHOLE[message, POINTER]]]], status: readOnly, field: entire[]]]; RETURN[IndexToTV[argsTV, index]]; }; -- end ArgOrResult EnclosingBody: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS[TypedVariable--localFrame--] = TRUSTED { -- maybe NIL IF IsRemote[tv] THEN { stb: SymbolTableBase = AcquireSTBFromRemoteGFH [[world: GetWorld[tv], worldIncarnation: CurrentIncarnation[GetWorld[tv]], gfh: LOOPHOLE[GetRemoteFrameHeader[RemoteFHFromTV[tv]].accesslink, WorldVM.ShortAddress]]]; rtr: REF TypedVariableRec _ NARROW[tv ! UNWIND => ReleaseSTB[stb]]; bti: BodyIndex; evalStack: WordSequence; isCatchFrame: BOOL; remoteFH: RemoteFrameHandle _ nilRemoteFrameHandle; contextPC: BOOL; level: BlockContextLevel; return: BOOL; WITH th: rtr.head SELECT FROM remoteFH => { bti _ th.bti; evalStack _ th.evalStack; isCatchFrame _ th.isCatchFrame; remoteFH _ th.remoteFrameHandle; contextPC _ th.contextPC; return _ th.return; }; ENDCASE => { ReleaseSTB[stb]; ERROR Error[reason: typeFault, type: TVType[tv]]; }; IF NullBTI[bti] THEN { IF isCatchFrame THEN { rfh: RemoteFrameHandle = RemoteFHFromTV[tv]; rgfh: WorldVM.ShortAddress _ LOOPHOLE[GetRemoteFrameHeader[rfh].accesslink]; bti _ SmallestBTIFromRemoteFH[rfh, stb, contextPC ! UNWIND => ReleaseSTB[stb]]; IF IsRootBTI[bti] THEN {ReleaseSTB[stb]; RETURN[NIL]}; -- not in the scope of any locals IF GetRemoteFrameHeader[remoteFH].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForRemoteFrame [[world: remoteFH.world, worldIncarnation: CurrentIncarnation[remoteFH.world], fh: LOOPHOLE[GetRemoteFrameHeader[remoteFH].staticlink - PrincOps.localbase, WorldVM.ShortAddress]]]; UNTIL IsBodyEncloser[er: tv, ee: bti, stb: stb] DO rmtFH: RemoteFrameHandle _ RemoteFHFromTV[tv]; IF LOOPHOLE[GetRemoteFrameHeader[rmtFH].accesslink, WorldVM.ShortAddress] # rgfh THEN {ReleaseSTB[stb]; ERROR}; IF GetRemoteFrameHeader[rmtFH].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForRemoteFrame [[world: rmtFH.world, worldIncarnation: CurrentIncarnation[rmtFH.world], fh: LOOPHOLE[GetRemoteFrameHeader[rmtFH].staticlink - PrincOps.localbase, WorldVM.ShortAddress]]]; ENDLOOP; rtr _ NARROW[tv, REF TypedVariableRec]; WITH th: rtr.head SELECT FROM remoteFH => { IF bti = th.bti THEN RETURN[tv]; evalStack _ NIL; -- NOTE isCatchFrame _ th.isCatchFrame; return _ th.return; contextPC _ th.contextPC; }; ENDCASE => ERROR; ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [fhType], head: [remoteFH[remoteFrameHandle: RemoteFHFromTV[tv], evalStack: evalStack, bti: bti, isCatchFrame: isCatchFrame, return: return, contextPC: contextPC]], status: mutable, field: entire[]]]]; } ELSE {ReleaseSTB[stb]; RETURN[NIL]} -- either no symbols or no locals }; -- end IF NullBTI[bti] IF CallableBTI[stb, bti] THEN IF (WITH BodyLevel[stb, bti] SELECT FROM -- TRUE => not a nested procedure t: BlockContextLevel.x => t.e <= bx.outerContextLevel, t: BlockContextLevel.y => t.e <= by.outerContextLevel, ENDCASE => ERROR) THEN {ReleaseSTB[stb]; RETURN[NIL]} ELSE { -- this is a frame for a nested procedure ReleaseSTB[stb]; IF GetRemoteFrameHeader[remoteFH].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; RETURN [TVForRemoteFrame [[world: remoteFH.world, worldIncarnation: CurrentIncarnation[remoteFH.world], fh: LOOPHOLE[GetRemoteFrameHeader[remoteFH].staticlink - PrincOps.localbase, WorldVM.ShortAddress]]]]; }; level _ BodyLevel[stb, bti]; bti _ ParentBody[stb, bti]; -- A Callable bt entry also describes the outer block locals IF IsRootBTI[bti] THEN bti _ nullBodyIndex; IF isCatchFrame AND (NOT NullBTI[bti]) AND level # BodyLevel[stb, bti] THEN { ReleaseSTB[stb]; -- we no longer need the stb IF GetRemoteFrameHeader[remoteFH].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForRemoteFrame [[world: remoteFH.world, worldIncarnation: CurrentIncarnation[remoteFH.world], fh: LOOPHOLE[GetRemoteFrameHeader[remoteFH].staticlink- PrincOps.localbase, WorldVM.ShortAddress]]]; rtr _ NARROW[tv, REF TypedVariableRec]; WITH th: rtr.head SELECT FROM remoteFH => { IF bti = th.bti THEN RETURN[tv]; evalStack _ NIL; -- NOTE isCatchFrame _ th.isCatchFrame; return _ th.return; contextPC _ th.contextPC; }; ENDCASE => ERROR } ELSE ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [fhType], head: [remoteFH[remoteFrameHandle: RemoteFHFromTV[tv], evalStack: evalStack, bti: bti, isCatchFrame: isCatchFrame, return: return, contextPC: contextPC]], status: mutable, field: entire[]]]]; } ELSE { -- local case of EnclosingBody stb: SymbolTableBase = AcquireSTBFromGFH[FHFromTV[tv].accesslink]; rtr: REF TypedVariableRec _ NARROW[tv ! UNWIND => ReleaseSTB[stb]]; bti: BodyIndex; evalStack: POINTER TO PrincOps.StateVector; isCatchFrame: BOOL; contextPC: BOOL; level: BlockContextLevel; return: BOOL; WITH th: rtr.head SELECT FROM fh => { bti _ th.bti; evalStack _ th.evalStack; isCatchFrame _ th.isCatchFrame; contextPC _ th.contextPC; return _ th.return; }; ENDCASE => { ReleaseSTB[stb]; ERROR Error[reason: typeFault, type: TVType[tv]]; }; IF NullBTI[bti] THEN { IF isCatchFrame THEN { fh: PrincOps.FrameHandle = FHFromTV[tv]; gfh: PrincOps.GlobalFrameHandle _ fh.accesslink; bti _ SmallestBTIFromFH[fh, stb, contextPC ! UNWIND => ReleaseSTB[stb]]; IF IsRootBTI[bti] THEN {ReleaseSTB[stb]; RETURN[NIL]}; -- not in the scope of any locals IF fh.staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForFrame[LOOPHOLE[fh.staticlink - PrincOps.localbase, PrincOps.FrameHandle]]; UNTIL IsBodyEncloser[er: tv, ee: bti, stb: stb] DO IF FHFromTV[tv].accesslink # gfh THEN {ReleaseSTB[stb]; ERROR}; IF FHFromTV[tv].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForFrame[LOOPHOLE[FHFromTV[tv].staticlink - PrincOps.localbase, PrincOps.FrameHandle]]; ENDLOOP; rtr _ NARROW[tv, REF TypedVariableRec]; WITH th: rtr.head SELECT FROM fh => { IF bti = th.bti THEN RETURN[tv]; evalStack _ NIL; -- NOTE isCatchFrame _ th.isCatchFrame; return _ th.return; contextPC _ th.contextPC; }; ENDCASE => ERROR; ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [fhType], head: [fh[fh: FHFromTV[tv], evalStack: evalStack, bti: bti, isCatchFrame: isCatchFrame, return: return, contextPC: contextPC]], status: mutable, field: entire[]]]]; } ELSE {ReleaseSTB[stb]; RETURN[NIL]} -- either no symbols or no locals }; -- end IF NullBTI[bti] IF CallableBTI[stb, bti] THEN IF (WITH BodyLevel[stb, bti] SELECT FROM -- TRUE => not a nested procedure t: BlockContextLevel.x => t.e <= bx.outerContextLevel, t: BlockContextLevel.y => t.e <= by.outerContextLevel, ENDCASE => ERROR) THEN {ReleaseSTB[stb]; RETURN[NIL]} ELSE { -- this is a frame for a nested procedure ReleaseSTB[stb]; IF FHFromTV[tv].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; RETURN[TVForFrame[LOOPHOLE[FHFromTV[tv].staticlink - PrincOps.localbase, PrincOps.FrameHandle]]]; }; level _ BodyLevel[stb, bti]; bti _ ParentBody[stb, bti]; -- A Callable bt entry also describes the outer block locals IF IsRootBTI[bti] THEN bti _ nullBodyIndex; IF isCatchFrame AND (NOT NullBTI[bti]) AND level # BodyLevel[stb, bti] THEN { ReleaseSTB[stb]; -- we no longer need the stb IF FHFromTV[tv].staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; tv _ TVForFrame[LOOPHOLE[FHFromTV[tv].staticlink - PrincOps.localbase, PrincOps.FrameHandle]]; rtr _ NARROW[tv, REF TypedVariableRec]; WITH th: rtr.head SELECT FROM fh => { IF bti = th.bti THEN RETURN[tv]; evalStack _ NIL; -- NOTE isCatchFrame _ th.isCatchFrame; return _ th.return; contextPC _ th.contextPC; }; ENDCASE => ERROR } ELSE ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [fhType], head: [fh[fh: FHFromTV[tv], evalStack: evalStack, bti: bti, isCatchFrame: isCatchFrame, return: return, contextPC: contextPC]], status: mutable, field: entire[]]]]; }; -- end local case of EnclosingBody }; -- end EnclosingBody Locals: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS[TypedVariable--record--] = TRUSTED { -- maybe NIL IF IsRemote[tv] THEN { stb: SymbolTableBase; rtr: REF TypedVariableRec; bti: BodyIndex; fh: RemoteFrameHandle = RemoteFHFromTV[tv]; type: Type; IF fh = nilRemoteFrameHandle THEN RETURN[NIL]; stb _ AcquireSTBFromRemoteGFH [[world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[GetRemoteFrameHeader[fh].accesslink, WorldVM.ShortAddress]]]; rtr _ NARROW[tv ! UNWIND => ReleaseSTB[stb]]; bti _ (WITH th: rtr.head SELECT FROM remoteFH => th.bti, ENDCASE => nullBodyIndex); IF NullBTI[bti] OR IsRootBTI[bti] OR NullSEI[BodyType[stb, bti]] THEN {ReleaseSTB[stb]; RETURN[NIL]}; type _ AcquireType[stb, BodyType[stb, bti] ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [type], head: rtr.head, status: mutable, field: entire[]]]]; } ELSE { stb: SymbolTableBase; rtr: REF TypedVariableRec; bti: BodyIndex; fh: PrincOps.FrameHandle = FHFromTV[tv]; type: Type; IF fh = NIL THEN RETURN[NIL]; stb _ AcquireSTBFromGFH[fh.accesslink]; rtr _ NARROW[tv ! UNWIND => ReleaseSTB[stb]]; bti _ (WITH th: rtr.head SELECT FROM fh => th.bti, ENDCASE => nullBodyIndex); IF NullBTI[bti] OR IsRootBTI[bti] OR NullSEI[BodyType[stb, bti]] THEN {ReleaseSTB[stb]; RETURN[NIL]}; type _ AcquireType[stb, BodyType[stb, bti] ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; RETURN[NEW[TypedVariableRec _ [referentType: [type], head: rtr.head, status: mutable, field: entire[]]]]; }; }; DynamicParent: PUBLIC SAFE PROC[tv: TypedVariable--localFrame--] RETURNS[TypedVariable--localFrame--] = TRUSTED { IF IsRemote[tv] THEN { remoteFH: RemoteFrameHandle = RemoteFHFromTV[tv]; cl: PrincOps.ControlLink; IF remoteFH.fh = 0 THEN RETURN[NIL]; cl _ AMProcessBasic.ReturnLink [remoteFH.world, LOOPHOLE[remoteFH.fh, PrincOps.FrameHandle]]; IF cl.proc OR cl.indirect THEN RETURN[NIL] ELSE RETURN[TVForRemoteFrame [[world: remoteFH.world, worldIncarnation: CurrentIncarnation[remoteFH.world], fh: LOOPHOLE[cl.frame, WorldVM.ShortAddress]]]]; } ELSE { fh: PrincOps.FrameHandle _ FHFromTV[tv]; cl: PrincOps.ControlLink; IF fh = NIL THEN RETURN[NIL]; cl _ AMProcessBasic.ReturnLink[WorldVM.LocalWorld[], fh]; IF cl.proc OR cl.indirect THEN RETURN[NIL] ELSE RETURN[TVForFrame[cl.frame]]; }; }; Globals: PUBLIC SAFE PROC[tv: TypedVariable--globalFrame--] RETURNS[TypedVariable--record--] = TRUSTED { IF IsRemote[tv] THEN { tvr: REF TypedVariableRec; gfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; type: Type; IF tv = NIL THEN RETURN[NIL]; tvr _ NARROW[tv]; gfh _ RemoteGFHFromTV[tv]; IF gfh = nilRemoteGlobalFrameHandle THEN RETURN[NIL]; { stb: SymbolTableBase = AcquireSTBFromRemoteGFH[gfh]; type _ AcquireType[stb, RootBodyType[stb] ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; }; RETURN[NEW[TypedVariableRec _ [referentType: [type], head: tvr.head, status: mutable, field: entire[]]]]; } ELSE { tvr: REF TypedVariableRec; gfh: PrincOps.GlobalFrameHandle; type: Type; IF tv = NIL THEN RETURN[NIL]; tvr _ NARROW[tv]; gfh _ GFHFromTV[tv]; IF gfh = NIL THEN RETURN[NIL]; LoadState.local.Acquire[]; type _ LoadState.local.GlobalFrameToType[gfh ! UNWIND => LoadState.local.Release[]]; LoadState.local.Release[]; IF type = nullType THEN { stb: SymbolTableBase = AcquireSTBFromGFH[gfh]; type _ AcquireType[stb, RootBodyType[stb] ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; }; RETURN[NEW[TypedVariableRec _ [referentType: [type], head: tvr.head, status: mutable, field: entire[]]]]; }; }; IsBodyEncloser: PROC[er: TypedVariable, ee: BodyIndex, stb: SymbolTableBase] RETURNS[ans: BOOL _ FALSE] = { rtr: REF TypedVariableRec _ NARROW[er]; WITH th: rtr.head SELECT FROM fh => {-- does th.bti enclose ee? WITH stb SELECT FROM t: SymbolTableBase.x => FOR bti: bx.BodyIndex _ NARROW[th.bti, BodyIndex.x].e, t.e.SonBti[bti] UNTIL bti = bx.nullBodyIndex DO IF bti = NARROW[ee, BodyIndex.x].e THEN RETURN[TRUE]; ENDLOOP; t: SymbolTableBase.y => FOR bti: by.BodyIndex _ NARROW[th.bti, BodyIndex.y].e, t.e.SonBti[bti] UNTIL bti = by.nullBodyIndex DO IF bti = NARROW[ee, BodyIndex.y].e THEN RETURN[TRUE]; ENDLOOP; ENDCASE => ERROR; }; remoteFH => {-- does th.bti enclose ee? WITH stb SELECT FROM t: SymbolTableBase.x => FOR bti: bx.BodyIndex _ NARROW[th.bti, BodyIndex.x].e, t.e.SonBti[bti] UNTIL bti = bx.nullBodyIndex DO IF bti = NARROW[ee, BodyIndex.x].e THEN RETURN[TRUE]; ENDLOOP; t: SymbolTableBase.y => FOR bti: by.BodyIndex _ NARROW[th.bti, BodyIndex.y].e, t.e.SonBti[bti] UNTIL bti = by.nullBodyIndex DO IF bti = NARROW[ee, BodyIndex.y].e THEN RETURN[TRUE]; ENDLOOP; ENDCASE => ERROR; }; ENDCASE => ERROR; }; AcquireBTIFromFH: PROC[fh: PrincOps.FrameHandle, contextPC: BOOL] RETURNS[isCatchFrame: BOOL, bti: BodyIndex] = { stb: SymbolTableBase = AcquireSTBFromGFH[fh.accesslink]; bti _ SmallestBTIFromFH[fh, stb, contextPC ! UNWIND => ReleaseSTB[stb]]; [isCatchFrame, bti] _ IsCatchFrame[fh, bti ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; RETURN[isCatchFrame, bti]; }; SmallestBTIFromFH: PROC[fh: PrincOps.FrameHandle, stb: SymbolTableBase, contextPC: BOOL] RETURNS[bti: BodyIndex] = { start: PrincOps.BytePC; epn: CARDINAL; framePC: PrincOps.BytePC = [(fh.pc - (IF contextPC THEN 0 ELSE 1))]; [epn, start] _ GetEp[framePC, fh.accesslink, stb]; bti _ ConvertCbti[ base: stb, pc: framePC, start: start, lastBti: LOOPHOLE[GetCBTI[stb, epn], BodyIndex] ]; }; SmallestBTIFromRemoteFH: PROC[rfh: RemoteFrameHandle, stb: SymbolTableBase, contextPC: BOOL] RETURNS[bti: BodyIndex] = { start: PrincOps.BytePC; epn: CARDINAL; remoteFrame: REF PrincOps.Frame = GetRemoteFrameHeader[rfh]; framePC: PrincOps.BytePC = [(remoteFrame.pc - (IF contextPC THEN 0 ELSE 1))]; [epn, start] _ GetRemoteEp[ pc: framePC, gf: [world: rfh.world, worldIncarnation: CurrentIncarnation[rfh.world], gfh: LOOPHOLE[remoteFrame.accesslink, ShortAddress]], stb: stb]; bti _ ConvertCbti[ base: stb, pc: framePC, start: start, lastBti: LOOPHOLE[GetCBTI[stb, epn], BodyIndex]]; }; GetCBTI: PUBLIC PROC[stb: SymbolTableBase, epn: CARDINAL] RETURNS[cbti: CallableBodyIndex] = { IsThisItX: PROC[bti: bx.BodyIndex] RETURNS[stop: BOOL] = { WITH NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM Callable => RETURN[(NOT inline) AND (epn = entryIndex)]; ENDCASE => RETURN[FALSE]; }; IsThisItY: PROC[bti: by.BodyIndex] RETURNS[stop: BOOL] = { WITH NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM Callable => RETURN[(NOT inline) AND (epn = entryIndex)]; ENDCASE => RETURN[FALSE]; }; bi: BodyIndex = WITH stb SELECT FROM t: SymbolTableBase.x => [x[t.e.EnumerateBodies[bx.rootBodyIndex, IsThisItX]]], t: SymbolTableBase.y => [y[t.e.EnumerateBodies[by.rootBodyIndex, IsThisItY]]], ENDCASE => ERROR; RETURN[LOOPHOLE[bi, CallableBodyIndex]]; }; ConvertCbti: PUBLIC PROC[lastBti: BodyIndex, pc, start: PrincOps.BytePC, base: SymbolTableBase] RETURNS[bti: BodyIndex] = { WITH base SELECT FROM t: SymbolTableBase.x => RETURN[[x[ConvertCbtiX[NARROW[lastBti, BodyIndex.x].e, pc, start, t.e]]]]; t: SymbolTableBase.y => RETURN[[y[ConvertCbtiY[NARROW[lastBti, BodyIndex.y].e, pc, start, t.e]]]]; ENDCASE => ERROR; }; ConvertCbtiX: PROC[lastBti: bx.BodyIndex, pc, start: PrincOps.BytePC, base: bx.SymbolTableBase] RETURNS[bti: bx.BodyIndex] = { bodyStart: PrincOps.BytePC; bti _ lastBti; DO FOR lastBti _ base.SonBti[bti], base.SiblingBti[lastBti] UNTIL lastBti = bx.nullBodyIndex DO WITH body: base.bb[lastBti] SELECT FROM Callable => LOOP; Other => { bodyStart _ [start + body.relOffset]; WITH body.info SELECT FROM External => IF pc IN [bodyStart..bodyStart+bytes) THEN {bti _ lastBti; EXIT}; ENDCASE; }; ENDCASE; REPEAT FINISHED => RETURN ENDLOOP; ENDLOOP; }; ConvertCbtiY: PROC[lastBti: by.BodyIndex, pc, start: PrincOps.BytePC, base: by.SymbolTableBase] RETURNS[bti: by.BodyIndex] = { bodyStart: PrincOps.BytePC; bti _ lastBti; DO FOR lastBti _ base.SonBti[bti], base.SiblingBti[lastBti] UNTIL lastBti = by.nullBodyIndex DO WITH body: base.bb[lastBti] SELECT FROM Callable => LOOP; Other => { bodyStart _ [start + body.relOffset]; WITH body.info SELECT FROM External => IF pc IN [bodyStart..bodyStart+bytes) THEN {bti _ lastBti; EXIT}; ENDCASE; }; ENDCASE; REPEAT FINISHED => RETURN ENDLOOP; ENDLOOP; }; GetEp: PUBLIC PROC[pc: PrincOps.BytePC, gf: PrincOps.GlobalFrameHandle, stb: SymbolTableBase] RETURNS [ep: EVRange, start: PrincOps.BytePC] = { FindMaxEI: PROC RETURNS [max: EVRange] = { GetMaxX: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOL] = { WITH NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM Callable => IF ~inline THEN max _ MAX[max, entryIndex]; ENDCASE; RETURN[FALSE]; }; GetMaxY: PROC [bti: by.BodyIndex] RETURNS [stop: BOOL] = { WITH NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM Callable => IF ~inline THEN max _ MAX[max, entryIndex]; ENDCASE; 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 Card: PROC[pc: PrincOps.BytePC] RETURNS[CARDINAL] = INLINE {RETURN[LOOPHOLE[pc, CARDINAL]]}; last: PrincOps.BytePC _ GetPc[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; }; GetPc: PUBLIC PROC[gf: PrincOps.GlobalFrameHandle, i: EVRange] RETURNS [PrincOps.BytePC] = { codeBase: LONG POINTER TO PrincOps.CSegPrefix = PrincOpsUtils.Codebase[gf]; wpc: CARDINAL = codeBase.entry[i].initialpc; -- GROAN RETURN[LOOPHOLE[wpc*2, PrincOps.BytePC]]; }; IsCatchFrame: PROC[frame: PrincOps.FrameHandle, bti: BodyIndex] RETURNS[BOOL, BodyIndex] = { L0Frame: PrincOps.FrameHandle; -- will be the frame that encloses the catch frame nextFrame: PrincOps.FrameHandle; tr: REF TypedVariableRec; IF frame = NIL THEN RETURN[FALSE, bti]; nextFrame _ AMProcessBasic.ReturnLink[WorldVM.LocalWorld[], frame].frame; IF nextFrame = NIL THEN RETURN[FALSE, bti]; IF nextFrame.accesslink # sigGF OR ~nextFrame.mark THEN RETURN[FALSE, bti]; IF frame.staticlink = NIL THEN DebuggerSwap.CallDebugger["Please call Paul Rovner"]; L0Frame _ LOOPHOLE[frame.staticlink - PrincOps.localbase, PrincOps.FrameHandle]; IF frame.accesslink # L0Frame.accesslink THEN RETURN[FALSE, bti]; tr _ NARROW[TVForFrame[L0Frame], REF TypedVariableRec]; WITH hd: tr.head SELECT FROM fh => IF bti = hd.bti THEN bti _ IF bti.brand = x THEN [x[bx.nullBodyIndex]] ELSE [y[by.nullBodyIndex]]; ENDCASE => ERROR; RETURN[TRUE, bti]; }; -- end IsCatchFrame END. RRTTypedFramesImpl.Mesa Russ Atkinson, September 23, 1983 4:24 pm Paul Rovner, November 9, 1983 10:49 pm TYPES CONSTANTS PUBLIC PROCEDURES raises typeFault all such tvs have the same (distinguished) type: fhType raises typeFault raises typeFault raises typeFault returns BTNull if still no symbols start proc frame XXX be careful about access via assign to RC variables that appear to be in a local frame (startproc) but really live in the GF. Also remote case returns BTNull if still no symbols here with bti # nullBodyIndex search up thru enclosing blocks till a callable one IF entryIndex = 0 THEN ERROR Error[reason: typeFault, type: TVType[tv]]; going up from a block or a body inside a startproc. here if the local frame has no enclosing callable body. This can't happen. returns a signal type if tv is for a catch frame, a procedure type if tv is for a local frame, raises TypeFault otherwise. bit offset of the field within the local frame Begin Here gotta do something different if this is an arg to a catch phrase message is either a pointer to a long arg record OR a single word value NOTE: if tv represents a block within a catch phrase, EnclosingBody may return the wrong context; i.e., the one enclosing the catch phrase. This won't come up if there is no block in the catch phrase at all; TVForFrame will detect it and do the right thing. It's harder to do the right thing here. The right solution is to put catch phrases in the body table!!! static nesting level, associated with a CTX (optimization: blocks, instead of counting up, get level of enclosing proc). 0 (lZ)=> off in the heap (not part of a frame...lifetime determined by some sort of runtime storage management, e.g. records, ctx for names of guys in an emum); 1 (lG) => global frame, outermost proc 2 (lL) and >2 => nested procedure. catch phrase in main prog would have a level of 2 (tho these are not recorded, because there are not symbol table entries for catch phrases. a fh tv will have NullBTI[bti] if there are no symbols for its referent or if it represents a frame for a startproc or catch phrase at a point outside the scope of locals get the bti of the smallest body that encloses the PC (if it's rootBodyIndex then RETURN[NIL]). Verify that this body is a body contained (not necessarily properly) within a frame somewhere up the static link. Return a tv for such a frame. starting with the frame of the most recent instance of the smallest enclosing static parent of the catch frame, search up the static chain to find the first frame that encloses the catch frame look up the static chain to find an encloser of bti (bti # rootBodyIndex) => one better exist Easy if we already have the right bti, otherwise get the new value of isCatchFrame No more enclosing blocks: this one is callable and not a catch frame means either that tv represents a frame for a startproc or catch phrase at a place outside the scope of locals. When the level changes inside of a catch phrase then we have to go through the static link (local 0) to get to the frame that corresponds to this bti. The static link points at local 0, not the frame base (=> subtract localbase). Easy if we already have the right bti, otherwise get the new value of isCatchFrame static nesting level, associated with a CTX (optimization: blocks, instead of counting up, get level of enclosing proc). 0 (lZ)=> off in the heap (not part of a frame...lifetime determined by some sort of runtime storage management, e.g. records, ctx for names of guys in an emum); 1 (lG) => global frame, outermost proc 2 (lL) and >2 => nested procedure. catch phrase in main prog would have a level of 2 (tho these are not recorded, because there are not symbol table entries for catch phrases. a fh tv will have NullBTI[bti] if there are no symbols for its referent or if it represents a frame for a startproc or catch phrase at a point outside the scope of locals get the bti of the smallest body that encloses the PC (if it's rootBodyIndex then RETURN[NIL]). Verify that this body is a body contained (not necessarily properly) within a frame somewhere up the static link. Return a tv for such a frame. starting with the frame of the most recent instance of the smallest enclosing static parent of the catch frame, search up the static chain to find the first frame that encloses the catch frame look up the static chain to find an encloser of bti (bti # rootBodyIndex) => one better exist Easy if we already have the right bti, otherwise get the new value of isCatchFrame No more enclosing blocks: this one is callable and not a catch frame means either that tv represents a frame for a startproc or catch phrase at a place outside the scope of locals. When the level changes inside of a catch phrase then we have to go through the static link (local 0) to get to the frame that corresponds to this bti. The static link points at local 0, not the frame base (=> subtract localbase). Easy if we already have the right bti, otherwise get the new value of isCatchFrame Cases: normal, startproc, block in startproc, catch frame, block in catch frame, catch frame in startproc. Possibly no symbols. all cases below can raise Error[noSymbols] normal: returns a vanilla-flavored (maybe callable) bti catch frame: returns a non-callable bti or nullBodyIndex (if outside scope of locals) startproc: returns a vanilla-flavored bti, maybe rootBodyIndex if fh is for a catch phrase, bti might be for a proc that contains it. if epn = 0 then this is a frame for the startproc or for a catchframe in the startproc if epn = 0 then this is a frame for the startproc or for a catchframe in the startproc finds the cbti for the specified entrypoint finds the bti for the smallest enclosing block finds the entrypoint index and its start pc for the proc containing the specified pc. BEWARE that if the pc is in a catch phrase, this returns the epn for the statically enclosing procedure of the catch phrase. body of GetEp begins here finds the start (byte) pc for the specified entrypoint index and GF return FALSE if caller is not the signaller detect situation where catch frame has no locals, thus no body table entry. return nullBodyIndex if isCatchFrame and it has no locals ส.1– "cedar" style˜procšœ™K™)Kšœ&™&—K˜šฯk ˜ šœ ˜Kšœเ˜เ—Kšœœ ˜!šœ˜ Kšœ/œ9˜j—šœ˜KšœN˜N—šœ˜KšœN˜N—Kšœ œ˜!Kšœ œ-˜<šœ ˜Kšœญœ ˜บ—Kšœœ˜+Kšœœ˜-Kšœœœ˜šœ ˜Kšœ†˜†—šœ ˜Kšœป˜ป—Kšœ œ ˜/šœ˜KšœŒ˜Œ—šœ˜Kšœก˜ก—Kšœ œ"˜3Kšœœ<˜I—K˜šœ˜Kšœซ˜ฒKšœ"˜)—šœ˜Kšœผ˜ภ—K™šœ™Kšœ œ˜(—K™šœ ™ šœ#˜#šœ˜ Kšœœ œ)˜W———K™Kšœ™™Kšœ™šฯn œœœœœœœœ˜Mšœ"˜,Kšœœ˜Kš œœœœœœœ˜EKšœœ,˜<—Kš œœœœœœ˜:Kšœ˜—K˜šž œœœ˜Kšœ˜Kšœ œœœ˜1Kšœœœ˜Kšœ œœ˜šœœœ˜Kšœ˜Kšœœœ˜Kš œœœœœ˜šœ4˜4Kšœ œœœ˜J—šœœ˜šœ˜šœ˜šœ!˜!KšœO˜O——Kšœ˜Kšœ˜Kšœ˜——Kšœ˜——K™Kšœ7™7Kšœ™šžœœœœ˜JKš œœœœœ˜šœœ˜šœœ˜šœœ˜Kšœœ ˜Kšœœ,˜<——Kšœœ,˜<—Kšœ˜—K˜šžœœœ!˜>Kšœ˜Kš œœœœœ˜šœœ˜KšœW˜W—Kšœ˜—K™Kšœ™šž œœœœ ˜QKš œœœœœ˜šœœ˜šœœ˜šœœ˜Kšœœ ˜Kšœœ,˜<——Kšœœ˜—Kšœ˜—K™Kšœ™š ž œœœœฯcœ˜LKšœŸœœ˜1šœœ˜Kšœ˜Kšœ:˜:šœ˜&šœ˜Kšœ+˜+Kšœ œœœ˜šœ˜Kšœ˜Kšœ0˜0Kšœœ=˜K—Kšœ˜—šœ˜Kšœ"˜"Kšœœœœ˜.šœ˜Kšœ˜Kšœ0˜0Kšœœ<˜J—Kšœ˜—šœ˜Kšœ&˜&šœ˜Kšœœ œ ˜(Kš œœ œœœœ˜;Kš œœ œœœœ˜˜K——Kšœ-˜2Kšœ˜—Kšœ˜—Kšœ˜——Kšœ˜—Kšœœœ,˜FKšœ˜Kšœ œœœ˜šœ˜šœ˜Kšœ/˜/Kšœœ>˜K——šœ!œ˜9šœœ˜Kšœœ*˜Lšœ2˜2Kšœœ˜@—Kšœœœ,˜HKšœ™šœ˜šœ˜šœ˜Kšœ/˜/šœœ%˜2Kšœ˜——Kšœ&˜&——Kšœœ˜*Kšœ˜KšœB˜HKšœ˜—Kšœ˜—Kšœ˜Kšœœ˜ Kšœ˜—šœŸ,˜2Kšœ˜Kšœœ˜Kšœ˜Kšœ˜Kš œœœœœ˜Kšœœ˜šœœ˜šœ˜šœ˜Kšœœ+˜5šœ˜Kšœ ˜ Kšœe™eKšœ+™+KšœŸ$˜5šœ˜Kšœ˜Kšœ3œœ˜HKšœ"™"Kšœœ˜šœ˜Kšœ2˜2Kšœ ˜ Kšœ˜Kšœœ,˜6Kšœ˜—šœœ!˜+Kšœ,˜,—Kšœ˜—Kšœ˜———Kšœœ,˜<—Kšœ™Kšœ˜Kš œœœœœ˜Kšœ'˜'Kšœ3™3šœ!œ˜9šœœ˜Kšœœ*˜Lšœ2˜2Kšœœ˜@—KšœH™HKšœ3™3Kšœ;˜;Kšœœ˜*Kšœ˜Kš œ œœœœœ˜8Kšœ˜—Kšœ˜—Kšœ˜Kšœ7™7Kšœ™Kšœ˜Kšœ˜—KšœŸ˜—K˜š žœœœœŸœ˜9KšœŸœœ˜Kš œ œœœœ˜%——K˜š žœœœœŸœ˜SKšœœœ"˜J—K˜š žœœœœŸœ˜QKšœœœ!˜I—K˜šž œœ˜KšœŸœ˜*Kšœ ˜ Kšœœœ˜(Kšœ˜Kšœ˜Kšœ ˜ Kšœœ˜ Kšœ  œ˜Kšœ ˜ Kšœœ˜Kšœœ˜Kšœœ˜K™Kšœ1™1Kšœ,™,Kšœ™šžœœ˜,Kšœ œœ˜;Kšœœœ˜'šœœ˜šœ˜Kšœ˜Kšœœœ œ˜;Kšœ˜—šœ ˜ Kšœ˜Kšœœœ œ˜;Kšœ˜—Kšœœ,˜<—Kšœ˜—K˜Kšœœœœ*˜@Kšœœ˜Kšœ(˜(Kšœœœ˜6Kšœ˜Kšœœœ˜6šœœ˜Kšœœ˜Kšœœ&˜6—Kšœœ˜"šœŸ>˜Dšžœœ/˜DKšœ&˜&Kšœ5˜5šœ œœ˜šœœœ˜Kšœ(œ$˜RKšœ(œ$˜RKšœœŸ"˜6——šœ œ˜šœœœ˜Kšœ œ"˜HKšœ œ"˜HKšœœŸ˜,——šœœ˜šœœœ˜Kšœ œ#˜IKšœ œ#˜IKšœœ˜——Kšœ.™.Kšœ$˜$Kšœ˜šœ˜Kšœœ˜1šœ œ˜$Kšœ˜KšœŸ$˜:Kšœ˜Kšœ<˜<—šœŸC˜HKšœ œ˜Kšœ˜šœ˜šœœœ˜Kšœœ˜$Kšœœ˜——Kšœ˜Kšœ=˜=—Kšœ˜—š˜šœ œ˜Kšœ˜šœ˜šœœœ˜Kšœœ˜#Kšœœ˜——Kšœ œœ œ˜Fšœ˜šœ ˜ KšœN˜N————KšœŸ˜—Kšœ ™ KšœL˜LKšœ ˜KšœŸ&˜*—K™Kšœ@™@Kšœ:˜:KšœG™GKšœ˜šœ˜Kšœœ˜.Kšœœ œ˜$šœ˜šœ˜Kšœ˜Kšœ˜Kšœ˜——Kšœ˜—šœœ˜šœ œ˜šœ˜šœ˜šœ˜šœ˜Kšœ˜Kšœ-˜-Kšœ+˜+———Kšœ˜Kšœ˜———šœ œ˜"šœ˜Kšœœœ œ˜8Kšœ˜Kšœ˜——Kšœ˜!KšœŸ˜—K˜š ž œœœœŸœ˜@KšœŸœœŸ ˜=Kšœๆ™๊šœœ˜šœ.˜.Kšœ˜Kšœ5˜5šœœ5˜DKšœ˜——Kšœœœœ˜CKšœ˜Kšœ˜Kšœœ˜Kšœ3˜3Kšœ œ˜Kšœ˜šœœ˜ Kšœx™xKšœ ™ Kšœ&™&Kšœ"™"Kšœ™—šœœ˜šœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—šœ˜ Kšœ˜Kšœ,˜1Kšœ˜—K™Kšœช™ช—šœœ˜šœœ˜Kšœ๐™๐Kšœ,˜,Kšœœ'˜LKšœ4œ˜Oš œœœœŸ!˜XKšœภ™ภ—šœ-˜2Kšœ6˜:—šœ˜šœ˜Kšœ5˜5šœœ*˜6Kšœ.˜.———Kšœ*˜/Kšœ3™3šœ˜Kšœ.˜.šœœE˜PKšœœ˜—Kšœ)™)šœ*˜/Kšœ6˜:—šœ˜šœ˜Kšœ2˜2šœœ'˜3Kšœ.˜.———Kšœ˜—Kšœœœ˜'šœœ˜šœ ˜ KšœR™RKšœœœ˜ Kšœ œŸ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœœ˜—Kšœ˜šœœ˜Kšœ˜šœ˜Kšœ0˜0Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜—Kšœ˜—KšœœœŸ!˜FKšœŸ˜—K˜šœ˜KšœD™Dš œœœœŸ!˜KKšœ7˜7Kšœ7˜7Kšœœ˜—Kšœœœ˜#šœŸ)˜0Kšœ˜šœ-˜2Kšœ6˜:—š˜šœ˜Kšœ˜Kšœ7˜7šœœ*˜8Kšœ3˜3———Kšœ˜——Kšœ˜KšœŸ<˜YKšœœ˜,Kšœo™ošœœœœ˜FšŸœ˜Kšœๅ™ๅKšœŸ˜-šœ-˜2Kšœ6˜:—šœ˜šœ˜Kšœ5˜5šœœ?˜KKšœ˜———Kšœœœ˜'šœœ˜šœ ˜ KšœR™RKšœœœ˜ Kšœ œŸ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—šœ˜Kšœ˜šœ˜Kšœ0˜0Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜—Kšœ˜—šœŸ˜%KšœB˜BKšœœœœ˜CKšœ˜Kšœ œœ˜+Kšœœ˜Kšœ œ˜Kšœ˜šœœ˜ Kšœx™xKšœ ™ Kšœ&™&Kšœ"™"Kšœ™—šœœ˜šœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœ˜ Kšœ˜Kšœ,˜1Kšœ˜——Kšœช™ชKšœ ˜šœ˜šœœ˜Kšœ๐™๐Kšœ(˜(Kšœ0˜0Kšœ-œ˜HKš œœœœŸ!˜XKšœภ™ภKšœœœ6˜QKšœœ<˜TKšœ*˜/Kšœ3™3šœ˜Kšœœœ˜?Kšœ)™)šœ˜ Kšœ6˜:—šœœ.˜FKšœ˜—Kšœ˜—Kšœœœ˜'šœœ˜šœ˜KšœR™RKšœœœ˜ Kšœ œŸ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœœ˜—Kšœ˜šœ˜Kšœ˜šœ˜šœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜——Kšœ˜Kšœ˜—Kšœ˜—KšœœœŸ!˜FKšœŸ˜—šœ˜KšœD™Dš œœœœŸ!˜KKšœ7˜7Kšœ7˜7Kšœœ˜—Kšœœœ˜#šœŸ)˜0Kšœ˜šœ˜ Kšœ6˜:—šœ œ.˜HKšœ!˜!—Kšœ˜——Kšœ˜KšœŸ<˜YKšœœ˜,Kšœo™oKšœœœœ˜Fšœ˜Kšœๅ™ๅKšœŸ˜-šœ˜ Kšœ6˜:—šœœ.˜FKšœ˜—Kšœœœ˜'šœœ˜šœ˜KšœR™RKšœœœ˜ Kšœ œŸ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜šœœ˜Kšœ˜šœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜—KšœŸ"˜&—KšœŸ˜—K™š žœœœœŸœ˜9KšœŸ œœŸ ˜9šœ œ˜Kšœ˜Kšœœ˜Kšœ˜Kšœ+˜+Kšœ ˜ Kšœœœœ˜.šœ˜šœ˜Kšœ/˜/Kšœœ>˜K——Kšœœœ˜-Kš œœœœœ˜Sšœœœ˜@Kšœœœ˜$—Kšœ-œ˜HKšœ˜šœœ˜KšœK˜K—Kšœ˜—šœ˜Kšœ˜Kšœœ˜Kšœ˜Kšœ(˜(Kšœ ˜ Kš œœœœœ˜Kšœ'˜'Kšœœœ˜-Kš œœœœœ˜Mšœœœ˜@Kšœœœ˜$—Kšœ-œ˜HKšœ˜šœœ˜KšœK˜K—Kšœ˜—Kšœ˜—K˜š ž œœœœŸœ˜@KšœŸœœ˜0šœœ˜Kšœ1˜1Kšœ˜Kšœœœœ˜$Kšœ˜Kšœœ%˜>Kšœ œ ˜Kšœœœ˜šœœ˜šœ˜Kšœ5˜5Kšœœ$˜0——Kšœ˜—šœ˜Kšœ(˜(Kšœ˜Kš œœœœœ˜Kšœ9˜9Kšœ œ œœœœœ˜MKšœ˜—Kšœ˜—K™š žœœœœŸœ˜;KšœŸ œœ˜,šœ ˜Kšœœ˜Kšœ:˜:Kšœ ˜ Kš œœœœœ˜Kšœœ˜Kšœ˜Kšœ"œœœ˜5šœ6˜6Kšœ,œ˜GKšœ˜—Kšœ˜šœœ˜KšœK˜K—Kšœ˜—šœ˜Kšœœ˜Kšœ ˜ Kšœ ˜ Kš œœœœœ˜Kšœœ˜Kšœ˜Kš œœœœœ˜Kšœ˜Kšœ/œ˜TKšœ˜šœ˜šœ˜Kšœ.˜.Kšœ,œ˜GKšœ˜Kšœ˜——šœœ˜KšœK˜K—Kšœ˜—Kšœ˜—K™šžœœ8˜LKšœœœ˜Kšœœœ˜'šœœ˜šœŸ˜!šœœ˜šœ˜šœœ(˜FKšœ˜Kš œœœœœœ˜8Kšœ˜——šœ˜šœœ(˜FKšœ˜Kš œœœœœœ˜8Kšœ˜——Kšœœ˜—Kšœ˜—šœ Ÿ˜'šœœ˜šœ˜šœœ(˜FKšœ˜Kš œœœœœœ˜8Kšœ˜——šœ˜šœœ(˜FKšœ˜Kš œœœœœœ˜8Kšœ˜——Kšœœ˜—Kšœ˜—Kšœœ˜—Kšœ˜—™Kšœ๘™๘—šžœœ&œ˜AKšœœ˜/Kšœ8˜8Kšœ-œ˜HKšœF™FKšœ-œ˜HKšœ˜Kšœ˜Kšœ˜—K˜šžœœ<œ˜XKšœ˜Kšœ˜Kšœœ˜Kšœ&œ œœ˜DKšœ2˜2KšœV™Všœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ œ˜/Kšœ˜—Kšœ˜—K˜šžœ˜Kšœ:œ˜CKšœ˜Kšœ˜Kšœœ˜Kšœ œ,˜Kšœ˜Kšœ œœœ2˜KKšœœ!Ÿ˜6Kšœœ˜)Kšœ˜K˜—šž œœ-˜?Kšœœ˜Kšœ Ÿ2˜RKšœ ˜ Kšœœ˜Kš œ œœœœ˜'KšœI˜IKš œ œœœœ˜+Kš œœœœœ˜KKšœ+™+Kšœœœ6˜TKšœ œ>˜PKšœ'œœœ˜AKšœK™KKšœœœ˜7šœ œ˜šœ˜šœ˜Kšœœœœ˜M——Kšœ9™9Kšœœ˜—Kšœœ˜KšœŸ˜—K˜—Kšœ˜K˜—…—‡ถฮ9