-- JaMVMImpl.mesa -- Pilot version -- Original version by Martin Newell, February 1979 -- Updated June 12, 1979 4:42 PM by MN -- Last changed by Bill Paxton, 14-Jan-82 14:03:03 -- Virtual memory is mapped onto a file, using the Pilot Space machinery. -- The maximum size of the file is fixed at the time the VM is started, -- but the actual file will grow in increments as necessary. -- VM address 0 maps onto the first word of page 2 (counting from 0) of the -- file, because page 0 is reserved for the leader page, and page 1 is used -- by the VM package for restart information. -- A simple marching allocator is provided. DIRECTORY JaMBasic, JaMVM, DCSFileTypes USING [tLeaderPage], Directory, File, Inline, Space; JaMVMImpl: MONITOR IMPORTS JaMVM, Directory, File, Inline, Space EXPORTS JaMVM = { OPEN JaMBasic; -- Types and constants AllocInfo: TYPE = MACHINE DEPENDENT RECORD[ password: CARDINAL, words: LONG CARDINAL, offset: CARDINAL]; vmPassword: CARDINAL = 48249; -- a more-or-less random number abase: CARDINAL = 1; -- base page in file for alloc info vmbase: CARDINAL = 2; -- base page in file for vm initialSize: CARDINAL = 256; sizeIncrement: CARDINAL = 16; maximumPages: CARDINAL = 4096; -- Globals vmfile: File.Capability _ File.nullCapability; aspace: Space.Handle _ Space.nullHandle; -- space for alloc info (1 page) vmspace: Space.Handle _ Space.nullHandle; -- space for all of vm vmpages: CARDINAL; -- number of pages currently mapped vmwords: LONG CARDINAL; -- number of words currently mapped alloc: LONG POINTER TO AllocInfo _ NIL; vm: PUBLIC Base _ NIL; -- Errors and Signals VMError: PUBLIC ERROR = CODE; BadVMPassword: PUBLIC SIGNAL = CODE; -- Procedures WordsForPages: PROC[p: CARDINAL] RETURNS[LONG CARDINAL] = INLINE { RETURN[Inline.LongMult[p,Space.wordsPerPage]] }; PagesForWords: PROC[w: LONG CARDINAL] RETURNS[CARDINAL] = INLINE { RETURN[Inline.LongDiv[w + Space.wordsPerPage - 1, Space.wordsPerPage]] }; OpenFile: PROC[name: LONG STRING] RETURNS[file: File.Capability, old: BOOLEAN] = { -- Open a file with the given name. -- If no file with that name exists, create one with initialSize pages. permissions: File.Permissions = File.read + File.write + File.grow; new: BOOLEAN _ FALSE; -- Look up the file file _ Directory.Lookup[fileName: name, permissions: permissions ! Directory.Error => SELECT type FROM fileNotFound => { new _ TRUE; CONTINUE }; ENDCASE]; IF new THEN { file _ Directory.CreateFile[fileName: name, fileType: DCSFileTypes.tLeaderPage, size: vmbase + initialSize]; file _ File.LimitPermissions[file,permissions]; } ELSE { type: File.Type _ File.GetAttributes[file].type; IF type#DCSFileTypes.tLeaderPage THEN ERROR VMError; IF File.GetSize[file]0 THEN 1 ELSE 0)]; MapUpTo[MAX[size,initialSize]]; }; Expand: PROC = { want: CARDINAL _ vmpages + sizeIncrement; -- want to add at least sizeIncrement need: CARDINAL _ PagesForWords[alloc.words + (IF alloc.offset>0 THEN 1 ELSE 0)]; pages: CARDINAL _ MAX[want,need]; MapUpTo[pages]; }; MapUpTo: PROC[pages: CARDINAL] = { filesize: CARDINAL _ vmbase + pages; -- required file size h: Space.Handle; IF pages>maximumPages THEN ERROR VMError; -- too many pages IF File.GetSize[vmfile] 0 THEN { alloc.words _ alloc.words + 1; alloc.offset _ 0 }; rptr _ LOOPHOLE[alloc.words]; alloc.words _ alloc.words + n; IF alloc.words > vmwords THEN Expand[]; RETURN[rptr]; }; AllocChars: ENTRY PROC[n: CARDINAL] RETURNS[Rptr,Offs] = { -- Increment allocataion pointer by length chars -- Generates VMError (from Expand) if no more room: rptr: Rptr _ LOOPHOLE[alloc.words]; offs: Offs _ alloc.offset; frac: CARDINAL _ offs + n MOD 2; alloc.words _ alloc.words + n/2 + frac/2; -- mind overflow! alloc.offset _ frac MOD 2; IF alloc.words >= vmwords THEN Expand[]; RETURN[rptr,offs]; }; AllocString: PUBLIC PROC[length: StringLength] RETURNS[string Object] = { string: string Object _ [L,string[length: length, text: , offset: ]]; [string.text,string.offset] _ AllocChars[length]; RETURN[string]; }; AllocArray: PUBLIC PROC[length: CARDINAL] RETURNS[array Object] = { array: array Object _ [L,array[length: length, base: ]]; array.base _ AllocWords[Inline.LongMult[length,SIZE[Object]]]; RETURN[array]; }; AllocTuples: PROC[size: CARDINAL] RETURNS[beg,end: TupleRptr] = { words: LONG CARDINAL _ Inline.LongMult[size,SIZE[Tuple]]; beg _ AllocWords[words]; end _ beg + words; RETURN[beg,end]; }; AllocDict: PUBLIC PROC[size: CARDINAL] RETURNS[dict Object] = { dict: dict Object _ [L,dict[AllocWords[SIZE[DictBody]]]]; dd: DictBody _ [curlen: 0, maxlen: 0, size: size, beg: , end: , curatt: 0, attach: [L,array[0,vmNIL]]]; [dd.beg,dd.end] _ AllocTuples[size]; JaMVM.PutDict[dict,dd]; RETURN[dict]; }; CopyArray: PUBLIC PROC[src,dst: array Object] = { count: CARDINAL _ MIN[src.length,dst.length]; -- number of objects to copy sptr: LONG POINTER _ @vm[src.base]; dptr: LONG POINTER _ @vm[dst.base]; words: LONG CARDINAL _ Inline.LongMult[count,SIZE[Object]]; chunk: CARDINAL = (LAST[CARDINAL]/SIZE[Object])*SIZE[Object]; WHILE words>0 DO w: CARDINAL _ Inline.LowHalf[MIN[words,chunk]]; Inline.LongCOPY[from: sptr, nwords: w, to: dptr]; sptr _ sptr + w; dptr _ dptr + w; words _ words - w; ENDLOOP; }; GetText: PUBLIC PROC[string: string Object, text: LONG STRING] = { count: CARDINAL _ MIN[string.length,text.maxlength]; stext: LONG POINTER TO TextBody _ @vm[string.text]; soffs: CARDINAL _ string.offset; FOR i: CARDINAL IN[0..count) DO text[i] _ stext[soffs+i] ENDLOOP; text.length _ count; }; PutText: PUBLIC PROC[string: string Object, text: LONG STRING] = { count: CARDINAL _ MIN[string.length,text.length]; stext: LONG POINTER TO TextBody _ @vm[string.text]; soffs: CARDINAL _ string.offset; FOR i: CARDINAL IN[0..count) DO stext[soffs+i] _ text[i] ENDLOOP; }; CopyString: PUBLIC PROC[src,dst: string Object] = { count: CARDINAL _ MIN[src.length,dst.length]; -- number of chars to copy stext: LONG POINTER TO TextBody _ @vm[src.text]; dtext: LONG POINTER TO TextBody _ @vm[dst.text]; soffs: CARDINAL _ src.offset; doffs: CARDINAL _ dst.offset; FOR i: CARDINAL IN[0..count) DO dtext[doffs+i] _ stext[soffs+i] ENDLOOP; }; }. Wyatt 24-Oct-81 14:42:23 add maxPages parameter to Start