-- RTLoaderImpl.Mesa -- Last Modified On July 7, 1983 10:07 am by Paul Rovner DIRECTORY AtomPrivate USING[UnsafeMakeAtom], BasicLoadState USING [ConfigID, ModuleToGlobalFrame, ConfigInfo, SetType, EnumerateConfigs, GlobalFrameToModule, TypeCode], BcdDefs USING [VersionStamp, MTIndex, SGIndex, RFNull, RFIndex, TFNull, TFIndex, FTSelf, BcdBase, MTHandle, ModuleIndex], BcdOps USING[ProcessModules], MPCodes USING[storageInitialized], PrincOps USING[GlobalFrameHandle, wordsPerPage], PrincOpsUtils USING[LongCOPY], ProcessorFace USING[SetMP], RCMap USING[Index, Base, invalidIndex], RCMapOps USING[Include, MapMap, FindMapMapEntry], RTBcd USING[AnyStamp, RTBase, StampList, TypeList, VersionID, TypeItem, RefLitItem], RTFlags USING[takingStatistics], RTSymbolDefs USING[nullXSymbolIndex], RTTypesBasicPrivate USING [AcquireTypeForLoader, UniqueTypeFinger, BlessMapStiStd, NotifyAtomRecType], SafeStorage USING[GetPermanentZone, Type, nullType, TypeIndex], SafeStorageOps USING[], SafeStoragePrivate USING[NewObject, PrivateHeapZone], Table USING[Base], TimeStamp USING[Null, Stamp], TypeStrings USING[Code, TypeString]; RTLoaderImpl: PROGRAM IMPORTS AtomPrivate, BasicLoadState, BcdOps, PrincOpsUtils, ProcessorFace, RCMapOps, RTTypesBasicPrivate, SafeStorage, SafeStoragePrivate EXPORTS SafeStorageOps = BEGIN OPEN AtomPrivate, BcdDefs, RTBcd, SafeStorage, SafeStoragePrivate; -- Statistics stats: RECORD[ nAtoms: INT _ 0, nLiteralWords: INT _ 0, -- allocated from PermanentZone nAtomPrintNameWords: INT _ 0 ]; Bump: PROC[p: POINTER TO INT, delta: INT _ 1] = INLINE {IF RTFlags.takingStatistics THEN p^ _ p^+delta}; RTBcdVersionMismatch: ERROR = CODE; configID: BasicLoadState.ConfigID = BasicLoadState.GlobalFrameToModule[LOOPHOLE[RTLoaderImpl]].config; bcd: BcdDefs.BcdBase = BasicLoadState.ConfigInfo[configID].bcd; atomType: Type _ nullType; -- the concrete type code for ATOM referents TypeTable: TYPE = RECORD[SEQUENCE length: NAT OF Type]; -- stuff used during CedarRuntime initialization ptt: LONG POINTER TO TypeTable _ NIL; rcMapMap: RCMapOps.MapMap _ NIL; -- communication between AcquireBasicTypes and AcquireBasicLiterals atomTypeChain: POINTER TO Type _ NIL; -- NOTE assume TypeTable entry in gf is 1 word -- this threads thru ATOM referent types in global frame type tables until atomType is known -- called by the Mesa runtime loader or the Cedar modeller after loading a bcd -- this initializes the type table and REF literal table in each new global frame. AcquireTypesAndLiterals: PUBLIC PROC[ bcd: BcdDefs.BcdBase, moduleToGFH: PROC[BcdDefs.ModuleIndex] RETURNS[PrincOps.GlobalFrameHandle], setType: PROC[PrincOps.GlobalFrameHandle, Type]] = { -- fill in the master tables (types, collectible literals) for the BCD. -- Then, foreach MT entry, fix up its type table and collectible literal table -- in the corresponding GF. rtBase: RTBcd.RTBase; rfBase, tfBase: Table.Base; l: NAT; ptrTypeTable: LONG POINTER TO TypeTable _ NIL; RefLitTable: TYPE = RECORD[SEQUENCE length: NAT OF REF ANY]; rrlt: REF RefLitTable _ NIL; rcmm: RCMapOps.MapMap _ NIL; -- foreach module in this bcd... doModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOLEAN _ FALSE] = { gfh: PrincOps.GlobalFrameHandle = moduleToGFH[mth.gfi]; WITH mth: mth SELECT FROM multiple => { IF mth.refLiterals # RFNull THEN {rl: RFIndex = mth.refLiterals; gfRefLiteralTable: LONG POINTER _ LONG[gfh+rfBase[rl].offset]; FOR i: NAT IN [0..rfBase[rl].length) DO LOOPHOLE[gfRefLiteralTable+i*SIZE[REF ANY], REF REF ANY]^ _ rrlt[rfBase[rl].frag[i]] --GFs are initially cleared to all NIL ENDLOOP}; IF mth.types # TFNull THEN {t: TFIndex = mth.types; pat: POINTER TO ARRAY [0..0) OF Type _ LOOPHOLE[gfh+tfBase[t].offset]; FOR i: NAT IN [0..tfBase[t].length) DO pat[i] _ ptrTypeTable[tfBase[t].frag[i]] ENDLOOP; IF NOT mth.tableCompiled AND mth.frameRefs THEN setType[gfh, LOOPHOLE[pat[mth.frameType], SafeStorage.Type]]; --fill in gftype in gftshadow-- }; }; ENDCASE}; -- START AcquireTypesAndLiterals HERE IF (NOT bcd.extended) OR (bcd.rtPages.pages = 0) THEN RETURN; -- old-style bcd or empty rtBase IF atomType = nullType THEN ERROR; -- better have done AcquireBasicTypes by now rtBase _ LOOPHOLE[bcd + bcd.rtPages.relPageBase*PrincOps.wordsPerPage]; IF rtBase.versionIdent # RTBcd.VersionID THEN ERROR RTBcdVersionMismatch; rfBase _ LOOPHOLE[bcd + bcd.rfOffset]; tfBase _ LOOPHOLE[bcd + bcd.tfOffset]; --now merge the BCD's RCMap base into the rcMapBase that is maintained by RT. -- construct rcmm: (BCD rcmapx -> RT rcmapx) IF rtBase.rcMapLength # 0 THEN rcmm _ RCMapOps.Include[LOOPHOLE[@rtBase[rtBase.rcMapBase]], rtBase.rcMapLength, PrivateHeapZone]; ptrTypeTable _ AcquireTypes[bcd, rcmm]; l _ rtBase[rtBase.refLitTable].length; IF l # 0 THEN {rrlt _ NEW[RefLitTable[l]]; -- collectible!! FOR i: NAT IN [0..l) DO rli: RefLitItem = rtBase[rtBase.refLitTable][i]; p: LONG POINTER _ (@rtBase[rtBase.litBase]) + rli.offset; IF rli.length = 0 THEN {rrlt[i] _ NIL; LOOP}; IF ptrTypeTable[rli.referentType] = atomType THEN {rrlt[i] _ UnsafeMakeAtom[LOOPHOLE[p]]; Bump[@stats.nAtoms]; Bump[@stats.nAtomPrintNameWords, rli.length]} ELSE {rrlt[i] _ NewObject[type: ptrTypeTable[rli.referentType], size: rli.length, zone: GetPermanentZone[]]; Bump[@stats.nLiteralWords, rli.length]; PrincOpsUtils.LongCOPY[from: p, to: LOOPHOLE[rrlt[i]], nwords: rli.length]}; ENDLOOP}; [] _ BcdOps.ProcessModules[bcd, doModule]; IF ptrTypeTable # NIL THEN PrivateHeapZone.FREE[@ptrTypeTable]; IF rcmm # NIL THEN PrivateHeapZone.FREE[@rcmm]; }; -- end AcquireTypesAndLiterals CopyTypesAndLiterals: PUBLIC PROC [ bcd: BcdDefs.BcdBase, mi: BcdDefs.ModuleIndex, old, new: PrincOps.GlobalFrameHandle] = { IF bcd.extended AND bcd.rtPages.pages # 0 THEN { -- this bcd has an RTBcd rtBase: RTBcd.RTBase = LOOPHOLE[bcd + bcd.rtPages.relPageBase*PrincOps.wordsPerPage]; rfBase: Table.Base = LOOPHOLE[bcd + bcd.rfOffset]; tfBase: Table.Base = LOOPHOLE[bcd + bcd.tfOffset]; findMTH: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOLEAN _ FALSE] = { IF mi IN [mth.gfi .. mth.gfi + mth.ngfi) -- this is the mth for the old global frame THEN { WITH mth: mth SELECT FROM multiple => { IF mth.refLiterals # BcdDefs.RFNull THEN { rl: BcdDefs.RFIndex = mth.refLiterals; gfRefLiteralTable: LONG POINTER _ LONG[new+rfBase[rl].offset]; oldGFRefLiteralTable: LONG POINTER _ LONG[old+rfBase[rl].offset]; FOR i: NAT IN [0..rfBase[rl].length) DO LOOPHOLE[gfRefLiteralTable+i*SIZE[REF ANY], REF REF ANY]^ _ LOOPHOLE[oldGFRefLiteralTable+i*SIZE[REF ANY], REF REF ANY]^; ENDLOOP; }; IF mth.types # BcdDefs.TFNull THEN { t: BcdDefs.TFIndex = mth.types; newPAT: POINTER TO ARRAY [0..0) OF SafeStorage.Type _ LOOPHOLE[new+tfBase[t].offset]; oldPAT: POINTER TO ARRAY [0..0) OF SafeStorage.Type _ LOOPHOLE[old+tfBase[t].offset]; PrincOpsUtils.LongCOPY[ from: oldPAT, nwords: tfBase[t].length * SIZE[SafeStorage.Type], to: newPAT ]; }; }; -- end multiple => ENDCASE; stop _ TRUE; }; -- end IF mi IN [mth.gfi .. mth.gfi + mth.ngfi) }; -- end findMTH IF rtBase.versionIdent # RTBcd.VersionID THEN ERROR; IF BcdOps.ProcessModules[bcd, findMTH].mth = NIL THEN ERROR; }; -- end IF bcd.extended AND bcd.rtPages.pages # 0 }; -- Whiz thru THIS config in the loadstate, acquiring Types. -- This config includes SafeStoragePackage.bcd. AcquireBasicTypes: PROC = {rtBase: RTBcd.RTBase; -- base of RTBcd tfBase: Table.Base; -- type table part of the RTBcd -- foreach module in this bcd... doModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOLEAN _ FALSE] = { gfh: PrincOps.GlobalFrameHandle = BasicLoadState.ModuleToGlobalFrame[configID, mth.gfi]; IF mth = NIL THEN ERROR; WITH mth: mth SELECT FROM multiple => IF mth.types # TFNull THEN {t: TFIndex = mth.types; pat: POINTER TO ARRAY [0..0) OF Type _ LOOPHOLE[gfh+tfBase[t].offset]; FOR i: NAT IN [0..tfBase[t].length) DO IF ptt[tfBase[t].frag[i]] = LAST[TypeIndex] -- special case for ATOMs ... link this into atomTypeChain. THEN {pat[i] _ LOOPHOLE[atomTypeChain]; atomTypeChain _ @pat[i]} ELSE pat[i] _ ptt[tfBase[t].frag[i]]; ENDLOOP; IF NOT mth.tableCompiled AND mth.frameRefs THEN BasicLoadState.SetType[gfh, LOOPHOLE[pat[mth.frameType]]]; --fill in gftype in gftshadow-- }; ENDCASE}; IF (NOT bcd.extended) OR (bcd.rtPages.pages = 0) THEN ERROR; -- this bcd (SafeStoragePackage and friends) better have somethin' to say rtBase _ LOOPHOLE[bcd + bcd.rtPages.relPageBase*PrincOps.wordsPerPage]; IF rtBase.versionIdent # RTBcd.VersionID THEN ERROR RTBcdVersionMismatch; tfBase _ LOOPHOLE[bcd + bcd.tfOffset]; IF rtBase.rcMapLength = 0 THEN ERROR; -- this bcd (SafeStoragePackage and friends) better have somethin' to say -- now merge the BCD's RCMap base into the rcMapBase that is maintained by CedarRuntime. -- construct rcMapMap: (BCD rcmapx -> CedarRuntime rcmapx) rcMapMap _ RCMapOps.Include[LOOPHOLE[@rtBase[rtBase.rcMapBase]], rtBase.rcMapLength, PrivateHeapZone]; ptt _ AcquireTypes[bcd, rcMapMap, TRUE]; [] _ BcdOps.ProcessModules[bcd, doModule]; }; -- end AcquireBasicTypes AcquireTypes: PROC [bcd: BcdDefs.BcdBase, rcMapMap: RCMapOps.MapMap, initializing: BOOLEAN _ FALSE] RETURNS[ptt: LONG POINTER TO TypeTable _ NIL] = { rtBase: RTBcd.RTBase = LOOPHOLE[bcd + bcd.rtPages.relPageBase*PrincOps.wordsPerPage]; typeTable: RTBase RELATIVE POINTER TO TypeList _ rtBase.typeTable; l: NAT _ rtBase[typeTable].length; IF l # 0 THEN { ptt _ PrivateHeapZone.NEW[TypeTable[l]]; FOR i: NAT IN [0..l) DO rcmi: RCMap.Index; ti: TypeItem = rtBase[typeTable][i]; st: RTBase RELATIVE POINTER TO StampList = rtBase.stampTable; utf: RTTypesBasicPrivate.UniqueTypeFinger _ [(IF ti.ut.version = AnyStamp THEN TimeStamp.Null ELSE rtBase[st][ti.ut.version]), [x[ti.ut.sei]]]; ts: TypeStrings.TypeString _ LOOPHOLE[@rtBase[rtBase.litBase] + ti.ct.index]; IF ti.sei = RTSymbolDefs.nullXSymbolIndex THEN {ptt[i] _ nullType; LOOP}; rcmi _ RCMapOps.FindMapMapEntry[rcMapMap, LOOPHOLE[ti.rcMap]]; IF rcmi = RCMap.invalidIndex THEN ERROR; -- to solve the atom type bootstrapping problem. IF initializing AND IsAtomRecTS[ts] THEN ptt[i] _ [LAST[TypeIndex]] -- special case for ATOMs ELSE {sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset]; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; version: TimeStamp.Stamp; IF sgb[ti.table].file = BcdDefs.FTSelf THEN version _ bcd.version ELSE version _ ftb[sgb[ti.table].file].version; ptt[i] _ RTTypesBasicPrivate.AcquireTypeForLoader [utf: utf, std: [symbolsStamp: version, bcd: bcd, sgi: ti.table], sei: [x[ti.sei]], ts: ts, rcmi: rcmi, canonicalize: TRUE, initializing: initializing]}; ENDLOOP}}; -- end AcquireTypes -- Called AFTER the allocator and ATOM machinery have been initialized. AcquireBasicLiterals: PUBLIC PROC[aType: Type] = {rtBase: RTBcd.RTBase; rfBase: Table.Base; l: NAT; RefLitTable: TYPE = RECORD[SEQUENCE length: NAT OF REF ANY]; rrlt: REF RefLitTable _ NIL; -- foreach module found in the loadstate for this config... doModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOLEAN _ FALSE] = { gfh: PrincOps.GlobalFrameHandle = BasicLoadState.ModuleToGlobalFrame[configID, mth.gfi]; IF mth = NIL THEN ERROR; WITH mth: mth SELECT FROM multiple => IF mth.refLiterals # RFNull THEN {rl: RFIndex = mth.refLiterals; gfRefLiteralTable: LONG POINTER _ LONG[gfh+rfBase[rl].offset]; FOR i: NAT IN [0..rfBase[rl].length) DO LOOPHOLE[gfRefLiteralTable+i*SIZE[REF ANY], REF REF ANY]^ _ rrlt[rfBase[rl].frag[i]] --GFs are initially cleared to all NIL ENDLOOP}; ENDCASE}; -- START AcquireBasicLiterals here -- first, fixup the atom type chain. atomType _ aType; RTTypesBasicPrivate.NotifyAtomRecType[atomType]; UNTIL atomTypeChain = NIL DO next: POINTER TO Type = LOOPHOLE[atomTypeChain^]; atomTypeChain^ _ atomType; atomTypeChain _ next; ENDLOOP; -- next, finish initilizing MapStiStd RTTypesBasicPrivate.BlessMapStiStd[]; -- next, get the BCD that contains this module (and RT.bcd) rtBase _ LOOPHOLE[bcd + bcd.rtPages.relPageBase*PrincOps.wordsPerPage]; rfBase _ LOOPHOLE[bcd + bcd.rfOffset]; -- now construct rrlt if there are any REF literals or ATOM constants, and store -- such REFs in indicated global frames l _ rtBase[rtBase.refLitTable].length; IF l # 0 THEN { rrlt _ NEW[RefLitTable[l]]; -- collectible!! Types have been acquired for RTLoaderImpl by this time. -- first acquire REF literals (the rope implementation, invoked by -- UnsafeMakeAtom, needs 'em) FOR i: NAT IN [0..l) DO rli: RefLitItem = rtBase[rtBase.refLitTable][i]; p: LONG POINTER _ (@rtBase[rtBase.litBase]) + rli.offset; IF rli.length = 0 THEN {rrlt[i] _ NIL; LOOP}; IF ptt[rli.referentType] = LAST[TypeIndex] -- special case for ATOMs THEN LOOP ELSE {rrlt[i] _ NewObject[type: ptt[rli.referentType], size: rli.length, zone: GetPermanentZone[]]; Bump[@stats.nLiteralWords, rli.length]; PrincOpsUtils.LongCOPY[from: p, to: LOOPHOLE[rrlt[i]], nwords: rli.length]}; ENDLOOP; [] _ BcdOps.ProcessModules[bcd, doModule]; -- now acquire ATOMs FOR i: NAT IN [0..l) DO rli: RefLitItem = rtBase[rtBase.refLitTable][i]; p: LONG POINTER _ (@rtBase[rtBase.litBase]) + rli.offset; IF rli.length = 0 THEN {rrlt[i] _ NIL; LOOP}; IF ptt[rli.referentType] = LAST[TypeIndex] -- special case for ATOMs THEN {rrlt[i] _ UnsafeMakeAtom[LOOPHOLE[p]]; Bump[@stats.nAtoms]; Bump[@stats.nAtomPrintNameWords, rli.length]} -- UnsafeMakeAtom invokes the ROPE package, which uses REF literals -- (but no ATOM literals). The parts of RT.config have no ATOM -- literals ELSE LOOP; ENDLOOP; [] _ BcdOps.ProcessModules[bcd, doModule]; }; -- now cleanup after the work on this BCD IF ptt # NIL THEN PrivateHeapZone.FREE[@ptt]; IF rcMapMap = NIL THEN ERROR; PrivateHeapZone.FREE[@rcMapMap]; -- and foreach config except this one in the basic loadstate invoke (vanilla) -- AcquireTypesAndLiterals. {p: PROC[otherConfigID: BasicLoadState.ConfigID] RETURNS [BOOL] = { IF otherConfigID # configID THEN { moduleToGFH: PROC[mx: BcdDefs.ModuleIndex]RETURNS[PrincOps.GlobalFrameHandle] ={ RETURN[BasicLoadState.ModuleToGlobalFrame[otherConfigID, mx]]; }; setType: PROC[gfh: PrincOps.GlobalFrameHandle, type: Type] = { BasicLoadState.SetType[gfh, LOOPHOLE[type, BasicLoadState.TypeCode]]; }; AcquireTypesAndLiterals[ bcd: BasicLoadState.ConfigInfo[otherConfigID].bcd, moduleToGFH: moduleToGFH, setType: setType ]; }; RETURN[FALSE]; }; [] _ BasicLoadState.EnumerateConfigs[p]; }; -- now set the maintenance panel code to indicate that SafeStorage is ready for business ProcessorFace.SetMP[MPCodes.storageInitialized]; }; -- end AcquireBasicLiterals IsAtomRecTS: PROC[ts: TypeStrings.TypeString] RETURNS[BOOLEAN] = {RETURN[ts.length = 1 AND ts[0] = LOOPHOLE[TypeStrings.Code[atomRec]]]}; --START HERE AcquireBasicTypes[]; END. ,GFs are initially cleared to all NIL Ê ¥˜Jš9Ïcœ:œÏk œžœ%žœ‰žœ‹žœžœ#žœ5žœžœžœ*žœ.žœVžœ%žœ,žœhžœBžœžœ(žœžœžœ#žœžœ—žœžœžœ@ ˜ procšœžœ˜Kšœžœ˜Kšœžœ&˜8Kšœžœ˜Kšœ˜K˜—Kš Ïnœžœžœžœžœ žœ˜/Kšžœžœžœ˜8K˜š œžœžœNžœu-œ žœžœžœ žœžœ 1œžœžœžœ žœžœDœžœžœžœ/œ]œOœSŸœžœžœ-žœžœ+žœ+HœOœœ8žœžœžœžœ žœžœžœžœ žœžœžœžœ žœžœžœ!œ žœ5žœžœžœFžœ žœžœžœ%žœHžœžœžœ-žœžœžœ.žœžœžœžœžœ*žœžœžœ5'œžœ žœžœ3žœžœžœžœžœ,žœžœžœ-žœ?žœžœžœžœ$žœžœDœ(žœ&œžœžœžœžœžœ!œžœžœžœ-œ žœ8žœ'žœžœ!žœ žœ{œžœžœžœ÷žœ žœ žœœ žœžœžœžœQžœžœ9žœžœ žœžœžœ:žœžœˆžœ¿žœ-žœ2žœžœžœžœžœžœžœžœ œŸœž œ˜ü%JšœX˜Xšžœžœžœ˜IJšœžœ6˜UJšœžœ˜2Jšœžœ˜2šœ žœ-˜:Jšžœžœžœ˜"Jšžœžœ"+˜Ušžœ˜šžœ žœž˜šœ ˜ šžœ!˜#šžœ˜Jšœ&˜&Jšœžœžœžœ˜>Jšœžœžœžœ˜AJšžœžœžœ˜$šž˜šžœžœžœžœžœžœžœ˜9Jšœžœžœžœžœžœžœžœ˜?—Jšœ$™$—Jšžœ˜Jšœ˜——Jšžœ˜šžœ˜Jšœ˜š œžœžœžœžœ˜3Jšœžœ˜!—š œžœžœžœžœ˜3Jšœžœ˜!—šœ˜Jšœ ˜ Jšœžœ˜2Jšœ ˜ Jšœ˜—Jšœ˜—Jšœ˜—Jšžœ˜—Jšœžœ˜ Jšœ/˜3—Jšœ˜—Jšžœ'žœžœ˜4Jšžœ+žœžœžœ˜