-- LaurelUnNewConfig.mesa; edited by Levin on April 8, 1983 10:50 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY BcdDefs USING [Base, MTIndex], BcdOps USING [BcdBase, MTHandle, ProcessModules], ControlDefs USING [ ControlLink, FrameCodeBase, GFT, GFTIndex, GFTItem, GFTNull, GlobalFrameHandle, NullGlobalFrame, PrefixHandle, PrefixInfo, TrapLink, UnboundLink], FrameDefs USING [EnumerateGlobalFrames, GlobalFrame, SwapInCode, UnNew], FrameOps USING [CodeHandle, Free], InlineDefs USING [BITAND], LoaderOps USING [CloseLinkSpace, OpenLinkSpace, ReadLink, WriteLink], LoadStateFormat USING [ModuleInfo], LoadStateOps USING [ AcquireBcd, ConfigIndex, EnterModule, EnumerateBcds, GetMap, GetModule, InputLoadState, MapRealToConfig, ReleaseBcd, ReleaseLoadState, ReleaseMap, Map, RemoveConfig], Mopcodes USING [zRBL], SegmentDefs USING [ DataSegmentAddress, DeleteFileSegment, FileSegmentHandle, SwapError, Unlock, VMtoDataSegment], SystemDefs USING [FreeSegment, SegmentSize]; LaurelUnNewConfig: PROGRAM IMPORTS BcdOps, FrameDefs, FrameOps, InlineDefs, LoaderOps, LoadStateOps, SegmentDefs, SystemDefs EXPORTS FrameDefs = BEGIN OPEN ControlDefs; ConfigIndex: TYPE = LoadStateOps.ConfigIndex; Map: TYPE = LoadStateOps.Map; BcdBase: TYPE = BcdOps.BcdBase; GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle; NullGlobalFrame: GlobalFrameHandle = ControlDefs.NullGlobalFrame; FileSegmentHandle: TYPE = SegmentDefs.FileSegmentHandle; UnNewConfig: PUBLIC PROCEDURE [link: UNSPECIFIED] = BEGIN OPEN LoadStateOps; config: ConfigIndex; map: Map; bcd: BcdBase; frame: GlobalFrameHandle ← FrameDefs.GlobalFrame[link]; FindOriginal: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN IF f # frame THEN BEGIN IF SameCode[frame, f] = identical AND ~f.copied THEN BEGIN frame ← f; RETURN[TRUE] END; END; RETURN[FALSE]; END; IF frame.copied THEN [] ← FrameDefs.EnumerateGlobalFrames[FindOriginal]; [] ← InputLoadState[]; [config: config] ← MapRealToConfig[frame.gfi]; bcd ← AcquireBcd[config]; map ← GetMap[config]; --UnBindConfig[config, bcd, map]; CleanupFrames[map]; CleanupGFT[map]; RemoveConfig[map, config]; ReleaseMap[map]; ReleaseBcd[bcd]; ReleaseLoadState[]; RETURN END; CodeMatch: TYPE = {identical, same, different}; SameCode: PROCEDURE [f1, f2: GlobalFrameHandle] RETURNS [cm: CodeMatch] = BEGIN o1, o2: BOOLEAN; seg1, seg2: FileSegmentHandle; fcb1, fcb2: ControlDefs.FrameCodeBase; seg1 ← FrameOps.CodeHandle[f1]; seg2 ← FrameOps.CodeHandle[f2]; fcb1 ← f1.code; fcb2 ← f2.code; IF seg1 = NIL AND seg2 = NIL THEN BEGIN fcb1.out ← fcb2.out ← FALSE; RETURN[IF fcb1 = fcb2 THEN identical ELSE different]; END; IF seg1 # seg2 THEN RETURN[different]; IF (o1 ← f1.code.out) AND (o2 ← f2.code.out) THEN RETURN[IF f1.code = f2.code THEN identical ELSE same]; FrameDefs.SwapInCode[f1]; FrameDefs.SwapInCode[f2]; cm ← IF f1.code = f2.code THEN identical ELSE same; SegmentDefs.Unlock[seg1]; SegmentDefs.Unlock[seg2]; IF ~f1.started THEN f1.code ← fcb1; IF ~f2.started THEN f2.code ← fcb2; RETURN END; DestroyCopy: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN FrameDefs.UnNew[f]; RETURN[FALSE]; END; CleanupFrames: PROCEDURE [map: Map] = BEGIN seg: FileSegmentHandle; frameSegment: POINTER ← NIL; frame: GlobalFrameHandle; i, ep: CARDINAL; nlinks: [0..256); FOR i IN [1..LENGTH[map]) DO deleteSeg: BOOLEAN ← FALSE; [frame: frame, epbase: ep] ← ControlDefs.GFT[map[i]]; IF frame = NullGlobalFrame OR ep # 0 THEN LOOP; seg ← FrameOps.CodeHandle[frame]; IF ~EnumerateCopies[frame, DestroyCopy].shared AND seg # NIL THEN deleteSeg ← TRUE; IF frame.alloced THEN BEGIN Align: PROCEDURE [POINTER, WORD] RETURNS [POINTER] = LOOPHOLE[InlineDefs.BITAND]; IF frame.codelinks THEN FrameOps.Free[frame] ELSE BEGIN nlinks ← FindNLinks[frame, seg]; FrameOps.Free[Align[frame - nlinks, 177774B]]; END; END ELSE frameSegment ← frame; IF deleteSeg THEN SegmentDefs.DeleteFileSegment[seg ! SegmentDefs.SwapError => CONTINUE]; ENDLOOP; IF frameSegment # NIL THEN SystemDefs.FreeSegment[frameSegment]; RETURN END; FindNLinks: PROCEDURE [frame: GlobalFrameHandle, seg: FileSegmentHandle] RETURNS [nlinks: CARDINAL] = BEGIN FrameDefs.SwapInCode[frame]; IF frame.code.highByte = 0 THEN BEGIN GetPrefixInfo: PROCEDURE [LONG POINTER] RETURNS [PrefixInfo] = MACHINE CODE BEGIN Mopcodes.zRBL, 1 END; prefix: PrefixInfo ← GetPrefixInfo[frame.code.longbase]; nlinks ← prefix.nlinks; END ELSE nlinks ← LOOPHOLE[frame.code.shortbase, PrefixHandle].header.info.nlinks; SegmentDefs.Unlock[seg]; RETURN; END; NextMultipleOfFour: PROCEDURE [n: UNSPECIFIED] RETURNS [UNSPECIFIED] = BEGIN RETURN[n + InlineDefs.BITAND[-n, 3B]] END; OP: TYPE = ORDERED POINTER; UnBindConfig: PROCEDURE [config: ConfigIndex, bcd: BcdBase, map: Map] = BEGIN OPEN LoadStateOps; bmap: Map; frameStart, frameEnd: OP; UnBind: PROCEDURE [c: ConfigIndex] RETURNS [BOOLEAN] = BEGIN bindee: BcdBase; IF c = config THEN RETURN[FALSE]; bindee ← AcquireBcd[c]; IF bindee.nImports # 0 THEN BEGIN bmap ← GetMap[c]; [] ← BcdOps.ProcessModules[bindee, AdjustLinks]; ReleaseMap[bmap]; END; ReleaseBcd[bindee]; RETURN[FALSE] END; AdjustLinks: PROCEDURE [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] = BEGIN gfi: ControlDefs.GFTIndex = bmap[mth.gfi]; frame: GlobalFrameHandle = ControlDefs.GFT[gfi].frame; changed: BOOLEAN; AdjustCopies: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN [] ← AdjustFrame[f, mth]; RETURN[FALSE]; END; IF frame = NullGlobalFrame OR mth.frame.length = 0 THEN RETURN[FALSE]; changed ← AdjustFrame[frame, mth]; IF changed AND frame.shared AND ~frame.codelinks THEN [] ← EnumerateCopies[frame, AdjustCopies]; IF changed THEN BEGIN info: LoadStateFormat.ModuleInfo ← GetModule[gfi]; info.resolved ← FALSE; EnterModule[rgfi: gfi, module: info]; END; RETURN[FALSE] END; AdjustFrame: PROCEDURE [frame: GlobalFrameHandle, mth: BcdOps.MTHandle] RETURNS [changed: BOOLEAN] = BEGIN i: CARDINAL; link: ControlDefs.ControlLink; changed ← FALSE; LoaderOps.OpenLinkSpace[frame, mth]; FOR i IN [0..mth.frame.length) DO link ← LoaderOps.ReadLink[i]; IF BoundHere[link, mth.frame.frag[i].vtag = var] THEN BEGIN link ← (SELECT link.tag FROM frame => TrapLink, ENDCASE => UnboundLink); LoaderOps.WriteLink[i, link]; changed ← TRUE; END; ENDLOOP; LoaderOps.CloseLinkSpace[frame]; RETURN END; BoundHere: PROCEDURE [link: ControlLink, var: BOOLEAN] RETURNS [BOOLEAN] = BEGIN OPEN FrameDefs; i: CARDINAL; gfi: GFTIndex ← GFTNull; IF var THEN RETURN[LOOPHOLE[link, OP] IN [frameStart..frameEnd)]; SELECT link.tag FROM procedure => gfi ← link.gfi; ENDCASE => RETURN[FALSE]; FOR i IN [1..LENGTH[map]) DO IF map[i] = gfi THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; IF bcd.nExports = 0 AND bcd.nModules # 1 THEN RETURN; frameStart ← LOOPHOLE[GFT[map[1]].frame]; IF bcd.nModules = 1 THEN BEGIN OPEN BcdDefs; mth: BcdOps.MTHandle = @LOOPHOLE[bcd + bcd.mtOffset, Base][FIRST[MTIndex]]; frameEnd ← LOOPHOLE[frameStart + mth.framesize] END ELSE BEGIN OPEN SegmentDefs; frameStart ← LOOPHOLE[DataSegmentAddress[VMtoDataSegment[frameStart]]]; frameEnd ← LOOPHOLE[frameStart + SystemDefs.SegmentSize[frameStart]]; END; [] ← EnumerateBcds[recentfirst, UnBind]; RETURN END; CleanupGFT: PROCEDURE [map: Map] = BEGIN OPEN ControlDefs; i: CARDINAL; FOR i IN [1..LENGTH[map]) DO GFT[map[i]] ← GFTItem[NullGlobalFrame, 0]; ENDLOOP; END; EnumerateCopies: PROCEDURE [ frame: GlobalFrameHandle, proc: PROCEDURE [GlobalFrameHandle] RETURNS [BOOLEAN]] RETURNS [result: GlobalFrameHandle, shared: BOOLEAN] = BEGIN FindCopies: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN IF f = frame THEN RETURN[FALSE]; SELECT SameCode[frame, f] FROM identical => BEGIN shared ← TRUE; IF f.copied AND proc[f] THEN RETURN[TRUE]; END; same => shared ← TRUE; ENDCASE; RETURN[FALSE]; END; shared ← FALSE; IF ~frame.shared THEN RETURN[NIL, FALSE]; RETURN[FrameDefs.EnumerateGlobalFrames[FindCopies], shared]; END; END...