<> <> <> <> <> <> <> DIRECTORY Basics USING [LongDiv, LongMult, LowHalf], PrincOps USING [wordsPerPage], PrincOpsUtils USING [LongCopy], TJaMBasic USING [DictBody, Object, Root, StringLength, TextBody, Tuple, TuplePtr], TJaMVM USING [PutDict], UnsafeStorage USING [GetSystemUZone, NewUObject]; TJaMVMImpl: MONITOR IMPORTS PrincOpsUtils, TJaMVM, Basics, UnsafeStorage EXPORTS TJaMVM = { <> Offs: TYPE = [0..1]; Ptr: TYPE = LONG POINTER; segment: Ptr _ NIL; -- to base of current chunk of storage size: LONG CARDINAL _ 0; -- size of current segment words: LONG CARDINAL _ 0; -- number of words allocated from this chunk offset: CARDINAL _ 0; totalWords: LONG CARDINAL _ 0; -- total # of words allocated by UnsafeStorage totalSegments: LONG CARDINAL _ 0; -- total # of objects allocated by UnsafeStorage <> WordsForPages: PROC[p: CARDINAL] RETURNS[LONG CARDINAL] = INLINE { RETURN[Basics.LongMult[p,PrincOps.wordsPerPage]] }; PagesForWords: PROC[w: LONG CARDINAL] RETURNS[CARDINAL] = INLINE { RETURN[Basics.LongDiv[w + PrincOps.wordsPerPage - 1, PrincOps.wordsPerPage]] }; Expand: PROC [atleast: LONG CARDINAL] = { want: CARDINAL _ PagesForWords[atleast]; pages: CARDINAL _ 4*((MAX[want,64]+1)/4); -- round up to multiple of 4 size _ WordsForPages[pages]; <> segment _ UnsafeStorage.NewUObject[size, UnsafeStorage.GetSystemUZone[]]; totalWords _ totalWords + size; totalSegments _ totalSegments + 1; words _ 0; offset _ 0; }; AllocWords: ENTRY PROC[n: LONG CARDINAL] RETURNS[Ptr] = { DO ptr: Ptr; IF offset > 0 THEN { words _ words + 1; offset _ 0 }; ptr _ segment + words; words _ words + n; IF words >= size THEN { Expand[n]; LOOP }; RETURN[ptr]; ENDLOOP; }; AllocChars: ENTRY PROC[n: CARDINAL] RETURNS[Ptr,Offs] = { DO ptr: Ptr _ segment + words; offs: Offs _ offset; frac: CARDINAL _ offs + n MOD 2; words _ words + n/2 + frac/2; -- mind overflow! offset _ frac MOD 2; IF words >= size THEN { Expand[n/2 + frac/2]; LOOP }; RETURN[ptr,offs]; ENDLOOP; }; AllocString: PUBLIC PROC[length: TJaMBasic.StringLength] RETURNS[string TJaMBasic.Object] = { string: string TJaMBasic.Object _ [L,string[length: length, text: , offset: ]]; [string.text,string.offset] _ AllocChars[length]; RETURN[string]; }; AllocArray: PUBLIC PROC[length: CARDINAL] RETURNS[array TJaMBasic.Object] = { array: array TJaMBasic.Object _ [L,array[length: length, base: ]]; array.base _ AllocWords[Basics.LongMult[length,SIZE[TJaMBasic.Object]]]; RETURN[array]; }; AllocTuples: PROC[size: CARDINAL] RETURNS[beg,end: TJaMBasic.TuplePtr] = { words: LONG CARDINAL _ Basics.LongMult[size,SIZE[TJaMBasic.Tuple]]; beg _ AllocWords[words]; end _ beg + words; RETURN[beg,end]; }; AllocDict: PUBLIC PROC[size: CARDINAL] RETURNS[dict TJaMBasic.Object] = { dict: dict TJaMBasic.Object _ [L,dict[AllocWords[SIZE[TJaMBasic.DictBody]]]]; dd: TJaMBasic.DictBody _ [curlen: 0, maxlen: 0, size: size, beg: , end: , curatt: 0, attach: [L,array[0,NIL]]]; [dd.beg,dd.end] _ AllocTuples[size]; TJaMVM.PutDict[dict,dd]; RETURN[dict]; }; CopyArray: PUBLIC PROC[src,dst: array TJaMBasic.Object] = { count: CARDINAL _ MIN[src.length,dst.length]; -- number of objects to copy sptr: LONG POINTER _ src.base; dptr: LONG POINTER _ dst.base; words: LONG CARDINAL _ Basics.LongMult[count,SIZE[TJaMBasic.Object]]; chunk: CARDINAL = (LAST[CARDINAL]/SIZE[TJaMBasic.Object])*SIZE[TJaMBasic.Object]; WHILE words>0 DO w: CARDINAL _ Basics.LowHalf[MIN[words,chunk]]; PrincOpsUtils.LongCopy[from: sptr, nwords: w, to: dptr]; sptr _ sptr + w; dptr _ dptr + w; words _ words - w; ENDLOOP; }; GetText: PUBLIC PROC[string: string TJaMBasic.Object, text: LONG STRING] = { count: CARDINAL _ MIN[string.length,text.maxlength]; stext: LONG POINTER TO TJaMBasic.TextBody _ 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 TJaMBasic.Object, text: LONG STRING] = { count: CARDINAL _ MIN[string.length,text.length]; stext: LONG POINTER TO TJaMBasic.TextBody _ 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 TJaMBasic.Object] = { count: CARDINAL _ MIN[src.length,dst.length]; -- number of chars to copy stext: LONG POINTER TO TJaMBasic.TextBody _ src.text; dtext: LONG POINTER TO TJaMBasic.TextBody _ dst.text; soffs: CARDINAL _ src.offset; doffs: CARDINAL _ dst.offset; FOR i: CARDINAL IN[0..count) DO dtext[doffs+i] _ stext[soffs+i] ENDLOOP; }; rootInfo: LONG POINTER TO TJaMBasic.Root _ NIL; GetRoot: PUBLIC PROC[root: LONG POINTER TO TJaMBasic.Root] = { root^ _ rootInfo^ }; PutRoot: PUBLIC PROC[root: LONG POINTER TO TJaMBasic.Root] = { rootInfo^ _ root^ }; Start: PUBLIC PROC = { rootInfo _ AllocWords[SIZE[TJaMBasic.Root]]; }; }.