ispoint
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Enter search term:
Next
regexp
Prev
Occur

X
Changesets
Project Outline
X

Menu
Reviving Smalltalk-76
+
Reading a NoteTaker image
The panel 'ImageReader' has two properties, ot and data, each are JS byte arrays.
Formats
ot is the object table, a sequence of 4-byte entries, retrievable by this.OTat(oop), where oop is an object pointer with the bottom two bits = 0. The entry encodes the data address, along with some other bits including a reference count that we can now ignore. The method dataAddress(oop) will retrieve the address, also taking into account the "dataBias" which I won't explain.
data is the object data space, a sequence of 2-byte words, retrievable by this.fieldOfObject(i, oop), where oop is an object pointer with the bottom two bits = 0, and i is the instance field number, with 1 being the index of the first field. An index of 0 would retrieve the class pointer of an object, but this must be masked by 0xFFC0 because the bottom 6 bits of the class word are used for the object's size in bytes. The method classOfOop will do this for you. This implies that all class oops have zero in the bottom 6 bits. This worked out nicely for OOZE's zones, but we will drop all that and go to the Squeak object format or whatever Bert is using internally. Note that if the size field is zero, then there is a word before the class with a 16-bit length. The method lengthBitsAt decodes this for you. It appears that the size field is the size in bytes, including the class(and size), so a string of length 1 has size=3, and a Point would have a size = 6.
The format of classes is (quoting from the system itself... title "<String> for identification, printing" myinstvars "<String> partnames for compiling, printing" instsize "<Integer> for storage management" messagedict "<MessageDict> for communication, compiling" classvars "<Dictionary/nil> compiler checks here" superclass "<Class> for execution of inherited behavior" environment "<Vector of SymbolTables> for external refs" fieldtype The instsize is an integer (ie low bit = 1) with the following interpretation: 0x8000 - fields are pointers, else not 0x4000 - fields are words, else bytes 0x2000 - instances are variable length 0x0FFE - instance size in words including class Thus Point has instsize = 0x8006 and Float has instsize = 04008 (nasty 3-word binary format)

The current strategy is first to read and decipher a NoteTaker image. Then we will get it running, as is, in Bert's SqueakJS, with Helge's code as a guide to particularities of the ST-76 VM and primitives. Then we should rescue the original source code by deciphering one of the full ST-76 systems or simply locating an appropriate sources file. Hopefully we can also reinstate the simple class context that got replaced in the NoteTaker.
We begin by capturing and deciphering a NoteTaker image as manifest in the pair of files, ObjectTable.nt and ObjectSpace.nt. This is the purpose of the 'ImageReader' panel.
Current State of things
In the Object Editor, the method printObj has two executable comments at the top. The first will print the first 32 objects in the image, the second will print the first 32 classes.
Getting Started
X

Menu
1003: <process> - in fact a circular pointer to this process.  I 
think the design was to have process chunks be linked together when 
one was not large enough (no evidence yet in code)
The format of a context frame within a process is...
    stack
    temps
    caller's pc
    nrArgs
    method
    mclass
    rcvr
    args
You can see that if args are pushed on stack (growing toward low 
memory) before the receiver, then the top of the stack *is* the 
beginning (bottom) of the next context frame
Here is the code where we start execution...
goBaby 
    [NoteTaker _ true.
    MethodKeeper _ (Vector new: 10) asStream.
    externalViews _ Set new vector: 10.
    [Dorado · [user currentDisplay: (Form new extent: 640 · 760 bits: 
(String new: 640 * 760 / 8) offset: nil)]
    DefaultTextStyle NoteTakerize.
    user currentDisplay: (Form new extent: 640 · 400 bits: (String 
new: 640 * 400 / 8) offset: nil)].
    while· true do·
        [self run]]
In order to start up, we simply set the pc to zero and fetch the 
first byte from the method.  My guess is that the value 7 in 'top' 
indicates the frame pointer for this top context frame (maybe delta 
relative to the end) and I have no idea what the 0, 42, 1 are doing, 
but I think we can ignore them for now.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// changed at Thu Jan 09 2014 22:44:41 GMT+0100 (CET) by bert  
this.addScript(function readObjects() {
    // create js objects for the st78 objects in ot+data
    this.st78Classes(); // ensure latest code is loaded
    var oopMap = {};
    for (var oop = 0; oop < this.ot.length; oop += 4)
        if (this.refCountOf(oop))
            oopMap[oop] = new St78.Object(oop);
    for (var oop in oopMap)
        oopMap[oop].installFromImage(oopMap);
    return oopMap;
}).tag([]);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
isPointers
lengthBitsAtAddr
loadImage
makeGlobalsItems
makeTreeItem
onSelect
OTat
printObj
readObjects
refCountOf
reset
shortPrint
snippets
st78Classes
stringAtAddr
Scripts
-- ALL --
Connections
+
+
-
-
<lively.morphic.Box#54AD1... - ImageReader>
Tag:
all
run
save
Tests

ObjectEditor
X

Menu
ImageReader
X

Menu

no image loaded
Load Image
Reset
this