Some Object Implementation Architectures
The Domain-only Object
The object styles that currently use this scheme are all one page of code. In this case the cost of the object is three nodes.
The domain's segment is composed of a node with one slot holding the memory key to the code shared by such objects and a page key to the private page of the object. An extra benefit of this plan is that the domain may hold a node key to the memory node and may thus use the extra 14 slots for keeping any sort of keys.
Code such as the following can be executed immediately following initiation by the factory to fulfill this plan.
KC SB,16,,(,TS) Buy the memory page.
KC MEM,17,(,TS) Install the page at address 1000.
KC MEM,40,((=X'03',1)),(,MEM) Set the databyte to LSS=3.
KC MYDOM,3,,(,TS) Get current read-only code
KC MEM,16,(,TS) Install code at 0
KC MYDOM,32+3,(,MEM) Make the new segment my memory.
These slots may also be used as windows for segments. If a memory key is placed in slot 4 of the node MEM that the first 4K of that segment shows at addresses 4XXX.
If the X'03' were replaced by X'04' in the above program, two benefits would ensue:
Complete Details of a Trivial but Useful Domain
In outline: we construct a new domain D, let D hold S, and place code in D that checks for order code 0. For order code 0, we return kt+2 to the caller and otherwise we jump (return) to S passing on the data and key parameters including the resume key from the caller.
Domain T is created {(p2,dc)}. S is placed in slot 3 of T {(p2,domswp)}. X'000300000400' is placed in the PSW of the domain. {This gives the domain the ability to do gate jumps and starts the program at X'400'. See (p1,d4) for format information.} We place some appropriate meter in the domain {(p1,d1)}. {The domain is available as it comes from the domain creator.}
We create a page P {(p2,sb)} to hold the code and working storage. We place the read-write page key to P in D3 of the domain {to become the memory tree root of the domain. {(p1,d3) This causes P to appear at addresses 000XXX within the domain. See (p1,memtree)}.
We place the code in P. We will describe the code here in standard assembler language.
In the above:
In the entry block, C8 limits the accepted string to 200 bytes. The 8F2 specifies that the order code is to be accepted and that all keys are to be accepted, and that the key in slot 2 is the page key of the parameter page that is to receive the parameter string from the caller. The 6789 names the slots of domain D that are to receive the four key arguments.
In the exit block F8 indicates that the four received keys are to be passed on to S. 32 indicates that the gate in slot 3 is to be jumped to {S} and that slot 2 holds the page key to the page that provides the parameter string. 6789 indicates that the same 4 slots that received the key parameters will provide the key parameters for S.
The exit block used when D refuses to execute order code 0 merely specifies that the key in slot 9 be jumped to. This is presumably the resume key to the caller.
Notice that domain D gets control only as control was to have been given to S. D gives control to S in such a way that S returns directly to the original caller rather than via D.
PL/I version of this code
KENTRY OCTO(OC) KEYSTO(A,B,C,D) STRINGTO(X); IF OC = 0 THEN KRETURN (D,KT+2); ELSE KRETURN (S,OC) KEYSFROM(A,B,C,D) STRINGFROM(X); STOP /* We should never get here */; END RESTRICT;
See the PL/I guide {(pli-guide,)} for a complete example.
The Life Cycle of the VSCK Segment
VCSK segments come from factories and there are many factories that produce VCSK segments. Two segments produced by the same factory have the same initial content. There is a commonly available VCSK segment factory that produces segments that are initially zero. These factories have no holes. Not even the segment keeper's logic need be trusted.
To provide copyable data with this mechanism one places his data in a VCSK segment S. When this data is complete one calls S (actually S's keeper) and asks for a factory. Thenceforth S will not be writeable by any key. The new factory will produce writable segments whose initial contents are those of S. A segment from the new factory is itself a VCSK segment and after possible modification can itself produce a factory generating copies of the modified segment. Thus the cycle continues.
For this discussion we term segments "good" if none of the ancestors have been deleted. It is "bad" if it is not good.
A VCSK segment is constructed by a uniform tree of nodes. This means that each node of the tree holds memory keys of SSC one less than themselves. Only the top node is red. Each memory key in an initial slot of a good segment is either a node key or a sense key. A sense key is placed in a newer segment and refers to a portion of an older (parent) segment. Node keys always refer to nodes of the current generation. Nodes at the bottom of the tree may hold read-only keys to a parent segment or read-write page keys to pages of the current generation.
In a bad segment some keys that had been either sense keys or read-only page keys may be replaced by DK(0).
The height of the tree is at least as high as the parent and higher if stores beyond the parent's power of 16 have occurred. There is special logic to assure that products of the primordial VCSK segment factory are short, their ancestor being 12 high!
Since all addresses within the current power of 16 are defined, messages to the segment keeper are due either to accesses beyond that power or to write faults (or accesses to DK(0) for bad segments).
When an access is made beyond the current power of 16 the tree is grown by producing references to the primordial zero segment until the current power is big enough.
From the relative address the segment keeper follows the chain of node keys until a sense key or a read-only page key is encountered. In the case of a sense key, a new node is bought and filled with the 16 sensory keys fetched with the sense key, and a node key to the new node with appropriate databyte to the new node replaces the sense key. If a read-only page is encountered a new page is bought and the data from the read-only page is copied to the new page and the read-write page key to the new page replaces the read-only page key. These actions eventually allow the new segment to be written.
When a VCSK segment keeper is asked for a new factory it first replaces the keys in the initial slots of the top (red) segment node with sense keys with the same databyte to the same nodes (or a read-only page key to the same page). It also sets a bit in the node's format key to remind itself that this segment is now sealed and may never be written again. The keeper invokes the copy key (kept since birth) to the factory that created it. A sense key to the recently modified top segment node is passed to the new factory as a sensory component. Products of the new factory will build an initial top segment with a new node and keys copied (with the sense key) from old top node. This completes the reproduction cycle and the keeper proceeds as described above in response to store faults.
First a trick to overcome an obstacle to obeying the length call:
Portions of the parental segment that are indeed zero (but not the primordial zero segment) are replaced by the primordial segment. This causes higher segments to be replaced as well but for at most 12 levels and 12 nodes.
The cost is avoided on subsequent queries and access to the segment may be made cheaper because the primordial segment is used rather than the special parental segment.
Let P be the largest power of 16 that divides x. Let a .unit be a size P part of a segment starting on a multiple of P. This establishes a level below which we may process subtrees of the segments as .units.
We establish a routine that on successive calls, returns two values, MK and addr. MK is a sense key to a nonzero .unit in SEGB and addr is the address within SEGB where MK appeared. Nodes above the magic level will be returned to SEGB's space bank. The keeper of SEGB executes this routine.
The SEGA keeper calls this routine and builds the required segment nodes to hold the returned memory keys.
The goodness of this scheme is that the work is limited to the real (as contrasted to virtual) size of the segment.
SEGA then uses the command DOMAINCREATOR__IDENTIFY_SEGMENT to get a domain key to SEGB's keeper. With this SEGA produces a start key SEGb with a databyte indicating the "return units" function. The call is SEGb(33,((4,log P));,,X==>0;,,,EX) where X is the node key to SEGB's node {strangely held by SEGA just now}. This is the beginning of a co-routine {during which SEGA will remain busy} that returns actual P sized units of which SEGB is composed. SEGA determines whether the key SEGB has the authority to destroy the indicated segment.
The statement EX(0;==>c,((6,address within SEGB));,,SK,EX) returns, on successive executions, the consecutive nonzero units of SEGB. On each call c=0 and SK is another unit or c=1 and SK and EX are DK(0). Material from SEGB is returned to SEGB's bank as this operation proceeds. At the termination of this sequence SEGB deletes itself.
This tree walk is different from the other tree walk in VCSK {the delete walk} in three ways:
there is no descent below level P,
There is always descent to level P even into ancestor segments.
This question is answered with very little computing.
This data base is small. It is very close to the theoretical limit.
The base constructor executes about one hundred instructions per character of input.
There is a parameter which at one extreem expands the size of the data base and at the other extreem leads to increased probability of reporting that a word is in a file when it is not. {The other kind of mistake is never made.}
If is very efficient to combine two data bases but impossible to backout files from a data base.
Files can be easily added to a data base but not deleted.
We will consider the case where the owner of the files wishes to hide the files from the programmer of the algorithm.
We use the term "xref" as a noun to name an object which includes such a data base and a reference to these algorithms.
There is an xref creator that takes as a parameter the size of the data base. An xref is returned with an empty set of files.
A call on an xref specifies a word and returns a bit vector that has the i'th bit on if the i'th file included the word and a very few other bits as well.
There is a call on an xref to "concatenate" two xref's -- namely the called xref and a passed xref.
Alternatively one might direct inquiries to both A and B and add incoming stories only to B. Each midnight A would be replaced by B and A would be replaced by an empty Xref.
There is a generally available key called the MEM_REF_MONITOR_CREATOR which accepts a space bank, meter, a memory key S and a gate G. Another memory key M is returned along with a gate H.
The key M is used where S would have been used, i.e., in the contexts whose references are to be monitored. The monitor has one of three states associated with each page address -- NA {no access}, RO or RW. The state for every page of a newly created monitor is NA.
When memory key M is accessed at a page whose state is NA, gate G is called {by the monitor} reporting the access address {relative to S or M}. After G returns the state of that page address is changed to allow the access.
H {presumably held by G,} can be used to explicitly alter the states of the pages of the monitor at any time.
The monitor might be programmed to report and pass on calls to the segment keeper of S as well as faults to the segment keeper. It could also be programmed to report the faulting that that keeper might attempt to the referencer. This fault signal could also be sent on to the original accessor.
This tool can be used to monitor memory access to the extent obviously provided by the hardware and it removes from the user the burden of contemplating the details of memory tree logic.