JaMVMImpl.mesa
Original version by Martin Newell, February 1979
Updated June 12, 1979 4:42 PM by MN
Bill Paxton, November 5, 1982 9:45 am
Russ Atkinson, July 22, 1983 7:43 pm
DIRECTORY
JaMBasic,
JaMVM,
Basics,
PrincOps,
PrincOpsUtils,
UnsafeStorage;
JaMVMImpl: MONITOR
IMPORTS PrincOpsUtils, JaMVM, Basics, UnsafeStorage
EXPORTS JaMVM = {
OPEN JaMBasic;
Globals
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
Procedures
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];
create a space to the hold monster
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: 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[Basics.LongMult[length,SIZE[Object]]];
RETURN[array];
};
AllocTuples: PROC[size: CARDINAL] RETURNS[beg,end: TuplePtr] = {
words: LONG CARDINAL ← Basics.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,NIL]]];
[dd.beg,dd.end] ← AllocTuples[size];
JaMVM.PutDict[dict,dd];
RETURN[dict];
};
CopyArray: PUBLIC PROC[src,dst: array Object] = {
count: CARDINALMIN[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[Object]];
chunk: CARDINAL = (LAST[CARDINAL]/SIZE[Object])*SIZE[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 Object, text: LONG STRING] = {
count: CARDINALMIN[string.length,text.maxlength];
stext: LONG POINTER TO 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 Object, text: LONG STRING] = {
count: CARDINALMIN[string.length,text.length];
stext: LONG POINTER TO 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 Object] = {
count: CARDINALMIN[src.length,dst.length]; -- number of chars to copy
stext: LONG POINTER TO TextBody ← src.text;
dtext: LONG POINTER TO 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 Root ← NIL;
GetRoot: PUBLIC PROC[root: LONG POINTER TO Root] = { root^ ← rootInfo^ };
PutRoot: PUBLIC PROC[root: LONG POINTER TO Root] = { rootInfo^ ← root^ };
Start: PUBLIC PROC = {
rootInfo ← AllocWords[SIZE[Root]];
};
}.