-- MMModules.mesa; edited by Forrest, July 15, 1980 2:45 PM DIRECTORY BcdDefs USING [NullLink, UnboundLink], ControlDefs USING [ ControlLink, EPRange, FrameCodeBase, FrameHandle, GFT, GFTIndex, GFTItem, GlobalFrameHandle, MainBodyIndex, LastAVSlot, NullEpBase, NullFrame, NullGlobalFrame, PrefixHandle], FrameDefs USING [ EnterGlobalFrame, EnumerateGlobalFrames, RemoveGlobalFrame, SwapInCode], FrameOps USING [ Alloc, FrameSize, Free, GetReturnFrame, SetReturnLink], InlineDefs USING [BITAND, COPY], MiscDefs, MMOps, MMSDEntries, SDDefs USING [SD, sGFTLength], SystemDefs USING [FreePages], TrapDefs USING [UnboundProcedure]; MMModules: PROGRAM IMPORTS FrameDefs, FrameOps, InlineDefs, SystemDefs, TrapDefs EXPORTS FrameDefs, MiscDefs, MMOps, MMSDEntries = PUBLIC BEGIN OPEN ControlDefs; -- Global Frame Table management gftrover: CARDINAL _ 0; -- okay to start at 0 because incremented before used NoGlobalFrameSlots: PUBLIC SIGNAL [CARDINAL] = CODE; EnumerateGlobalFrames: PUBLIC PROCEDURE [ proc: PROCEDURE [GlobalFrameHandle] RETURNS [BOOLEAN]] RETURNS [GlobalFrameHandle] = BEGIN i: GFTIndex; frame: GlobalFrameHandle; gft: POINTER TO ARRAY [0..0) OF GFTItem _ GFT; FOR i IN [0..SDDefs.SD[SDDefs.sGFTLength]) DO frame _ gft[i].frame; IF frame # NullGlobalFrame AND gft[i].epbase = 0 AND proc[frame] THEN RETURN[frame]; ENDLOOP; RETURN[NullGlobalFrame] END; EnterGlobalFrame: PUBLIC PROCEDURE [ frame: GlobalFrameHandle, nslots: CARDINAL] RETURNS [entryindex: GFTIndex] = BEGIN gft: POINTER TO ARRAY [0..0) OF GFTItem _ GFT; i, imax, n, epoffset: CARDINAL; i _ gftrover; imax _ SDDefs.SD[SDDefs.sGFTLength] - nslots; n _ 0; DO IF (i _ IF i>=imax THEN 1 ELSE i+1) = gftrover THEN SIGNAL NoGlobalFrameSlots[nslots]; IF gft[i].frame # NullGlobalFrame THEN n _ 0 ELSE IF gft[i].epbase = NullEpBase THEN n _ 0 ELSE IF (n _ n+1) = nslots THEN EXIT; ENDLOOP; entryindex _ (gftrover_i)-nslots+1; epoffset _ 0; FOR i IN [entryindex..gftrover] DO gft[i] _ GFTItem[frame, epoffset]; epoffset _ epoffset + EPRange; ENDLOOP; RETURN END; RemoveGlobalFrame: PUBLIC PROCEDURE [frame: GlobalFrameHandle] = BEGIN gft: POINTER TO ARRAY [0..0) OF GFTItem _ GFT; sd: POINTER TO ARRAY [0..0) OF CARDINAL _ SDDefs.SD; i: CARDINAL; FOR i _ frame.gfi, i+1 WHILE i RETURN[FALSE]; ENDLOOP; RETURN[gft[g.gfi].frame = g] END; InvalidFrame: PUBLIC SIGNAL [frame: FrameHandle] = CODE; ValidateFrame: PUBLIC PROCEDURE [f: FrameHandle] = BEGIN IF ~ValidFrame[f] THEN SIGNAL InvalidFrame[f]; END; ValidFrame: PROCEDURE [f: FrameHandle] RETURNS[BOOLEAN] = BEGIN RETURN[LOOPHOLE[f, ControlLink].tag = frame AND ValidGlobalFrame[f.accesslink]] END; GlobalFrame: PUBLIC PROCEDURE [link: UNSPECIFIED] RETURNS [GlobalFrameHandle] = BEGIN OPEN l: LOOPHOLE[link, ControlLink]; DO SELECT l.tag FROM frame => BEGIN IF link = 0 THEN RETURN[NullGlobalFrame]; IF ValidGlobalFrame[link] THEN RETURN[link]; IF ValidGlobalFrame[l.frame.accesslink] THEN RETURN[l.frame.accesslink]; RETURN[NullGlobalFrame] END; procedure => RETURN[GFT[l.gfi].frame]; indirect => link _ l.link^; unbound => link _ SIGNAL TrapDefs.UnboundProcedure[link]; ENDCASE ENDLOOP END; Copy: PUBLIC PROCEDURE [old: GlobalFrameHandle] RETURNS [new: GlobalFrameHandle] = BEGIN linkspace, ngfi: CARDINAL _ 0; FrameDefs.SwapInCode[old]; [new, linkspace, ngfi] _ AllocGlobalFrame[old]; new _ new + linkspace; new^ _ [gfi:, unused: 0, alloced: TRUE, shared: TRUE, copied: TRUE, started: FALSE, trapxfers: FALSE, codelinks: old.codelinks, code: old.code, global:]; new.gfi _ FrameDefs.EnterGlobalFrame[new, ngfi]; new.code.offset _ old.code.shortbase - old.code.handle; new.code.out _ TRUE; new.global[0] _ NullGlobalFrame; old.shared _ TRUE; IF linkspace # 0 THEN InlineDefs.COPY[ from: old-linkspace, to: new-linkspace, nwords: linkspace]; RETURN END; MakeFsi: PUBLIC PROCEDURE [words: CARDINAL] RETURNS [fsi: CARDINAL] = BEGIN FOR fsi IN [0..LastAVSlot] DO IF FrameOps.FrameSize[fsi] >= words THEN RETURN; ENDLOOP; RETURN[words] END; AllocGlobalFrame: PROCEDURE [old: GlobalFrameHandle] RETURNS [frame: GlobalFrameHandle, linkspace, ngfi: CARDINAL] = BEGIN pbody: POINTER; cp: PrefixHandle _ old.code.shortbase; pbody _ cp+CARDINAL[cp.entry[MainBodyIndex].initialpc]; linkspace _ IF ~old.codelinks THEN cp.header.info.nlinks + InlineDefs.BITAND[-LOOPHOLE[cp.header.info.nlinks, INTEGER], 3B] ELSE 0; frame _ FrameOps.Alloc[MakeFsi[(pbody-1)^+linkspace]]; ngfi _ cp.header.info.ngfi; RETURN END; UnNew: PUBLIC PROCEDURE [frame: GlobalFrameHandle] = BEGIN nlinks: CARDINAL; sharer: GlobalFrameHandle _ NullGlobalFrame; original: GlobalFrameHandle _ NullGlobalFrame; copy: GlobalFrameHandle _ NullGlobalFrame; nothers: CARDINAL _ 0; RemoveAllTraces: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN cm: CodeMatch; IF f#frame THEN BEGIN IF f.global[0] = frame AND ~f.started THEN f.global[0] _ NullFrame; cm _ SameCode[f, frame]; IF cm # different THEN BEGIN nothers _ nothers + 1; sharer _ f; IF cm = identical THEN IF f.copied THEN copy _ f ELSE original _ f; END; END; RETURN[FALSE]; END; FrameDefs.SwapInCode[frame]; [] _ FrameDefs.EnumerateGlobalFrames[RemoveAllTraces]; FrameDefs.RemoveGlobalFrame[frame]; IF frame.shared THEN BEGIN IF nothers = 1 THEN sharer.shared _ FALSE END ELSE SystemDefs.FreePages[frame.code.handle]; IF frame.alloced THEN BEGIN Align: PROCEDURE [POINTER, WORD] RETURNS [POINTER] = LOOPHOLE[InlineDefs.BITAND]; IF frame.codelinks THEN FrameOps.Free[frame] ELSE FrameOps.Free[Align[frame - nlinks, 177774B]] END; END; CodeMatch: TYPE = {identical, same, different}; SameCode: PROCEDURE [f1, f2: GlobalFrameHandle] RETURNS [cm: CodeMatch] = BEGIN fcb1, fcb2: ControlDefs.FrameCodeBase; fcb1 _ f1.code; fcb2 _ f2.code; IF f1.code.handle # f2.code.handle THEN RETURN[different]; FrameDefs.SwapInCode[f1]; FrameDefs.SwapInCode[f2]; cm _ IF f1.code = f2.code THEN identical ELSE same; IF ~f1.started THEN f1.code _ fcb1; IF ~f2.started THEN f2.code _ fcb2; RETURN END; LockCode, UnlockCode: PROCEDURE [link: UNSPECIFIED] = BEGIN END; MakeCodeResident, SwapOutCode: PROCEDURE [f: GlobalFrameHandle] = LockCode; GetCaller: PROCEDURE RETURNS [PROGRAM] = BEGIN RETURN[LOOPHOLE[FrameOps.GetReturnFrame[].returnlink.frame.accesslink]]; END; IsBound: PROCEDURE [link: UNSPECIFIED] RETURNS [BOOLEAN] = BEGIN RETURN[link # BcdDefs.UnboundLink AND link # BcdDefs.NullLink]; END; SelfDestruct: PROCEDURE = BEGIN destructee: FrameHandle _ FrameOps.GetReturnFrame[]; FrameOps.SetReturnLink[destructee.returnlink]; UnNew[GlobalFrame[destructee]]; FrameOps.Free[destructee]; RETURN END; SetBlock: PROCEDURE [p:POINTER, v:UNSPECIFIED, l:CARDINAL] = BEGIN IF l=0 THEN RETURN; p^ _ v; InlineDefs.COPY[from:p, to:p+1, nwords:l-1]; END; Zero: PROCEDURE [p:POINTER, l:CARDINAL] = BEGIN IF l=0 THEN RETURN; p^ _ 0; InlineDefs.COPY[from:p, to:p+1, nwords:l-1]; END; FakeModulesCode: PROCEDURE [p: PROGRAM] RETURNS [POINTER] = BEGIN frame: GlobalFrameHandle; FrameDefs.SwapInCode[frame _ GlobalFrame[p]]; RETURN[frame.code.shortbase]; END; END...