PROPOSED TAMARIN OPCODES FOR COMMON LOOPS Permutation Vector This is a vector used to relocate slot numbers of instances. There are two basic types of permutation vectors: simple and complex. Simple permutation vectors will contain the relocation numbers for one class, so the relocation process will be performed by reading the nth item in the permutation vector to get the offset into the slot area of the nth slot. Complex permutation vectors contain pointers to the permutation vectors for each class used in a method. Eash class is assigned an index into the complex permutation vector to find a pointer to the simple permutation vector for that class. - Why not combine the complex PV's into one PV where each class has an offset into the PV? This would simplify the the slot access since the class offset can be added to slot offset & the simple slot access method used. (Or do you not know the # slots a class will use at compile time thus not being able to assign an offset?) Wrappers When wrappers are mentioned what is meant is the pointer to the wrapper location, not what is in the wrapper itself. The following proposed opcodes make the following assumptions: - There is a fixed cell reserved for the permutation vector (PV) - Normal function calls always Nil the PV - There exists a type table indexed by the 8 tag & subtype bits which returns a wrapper for each type. I. Slot Access a. Simple PV (only one class) This opcode is used to access data contained in the slots of an instance. The operands for the opcode are: Tos - Ptr to the instance IBufN - Slot number to access PV - Ptr to Permutation vector in the reserved cell The semantics of the opcode are to retreive the value of the desired slot from an instance. The permutation vector must be accessed to find the correct offset into the instance slots of the desired item. The resulting slot value is then placed at Tos. The steps the opcode must take are: - Arg _ ReadMemory[PV + IBufN] This gets slot displacement - Temp _ ReadMemory[Tos + n] This gets address of slots - Tos _ ReadMemory[Temp + Arg] This reads the slot This opcode must Ufn if the PV entry is Nil, so that the PV can be rebuilt and deposited in the special location. - If the slot address is cached in the stack frame the extra memory reference can be avoided, but a microinstruction to access the cache location may still be necessary, unless the slot address was in a fixed cache location. b. Complex PV (several classes) This operation requires several opcodes. They are used to access data contained in the slots of an instance when there is more than one class input to a method. They are split into two opcodes so that the two IBufN constants can be part of each opcode thus giving the microcode faster access to them. The first opcode must determine the correct PV entry. The operands for this opcode are: Tos - ptr to the instance IBufN - Position of desired PV PV - Ptr to Permutation vector in the reserved cell - Tos+1 _ ReadMemory[PV + IBufN] Get PV for desired class with the resulting PV being pushed onto the stack. This opcode must Ufn if the PV entry is Nil, so that the PV entry can be rebuilt. - What is needed to rebuild the PV? If is is a complex PV then more than an instance should be required (i.e. all the classes used in the method). The next opcode accesses a slot based on the PV at Tos. Its operands are: Tos-1 - ptr to the instance Tos - ptr to the PV IBufN - Slot number to access with the PV being popped from the stack and then the slot placed at the new Tos. The steps for this opcode would be: - Arg _ ReadMemory[Tos + IBufN] - Temp _ ReadMemory[Tos-1 + n] - Tos _ Tos - 1 - Tos _ ReadMemory[Temp + Arg] II. Method Call A method call performs a method lookup based on the class or classes of one or more of the parameters. The simple method call will perform the lookup only for one class, when it is the first parameter. A method call is invoked through the normal function call mechanism with the definition cell of the called item being a special method subtype. The microcode will then have to perform the following: First the wrapper for the 1st parameter must be found. This will be performed by indexing into a type table based on the type bits of the parameter, unless the parameter is an instance, in which case the actual wrapper for the instance will be used. Once the wrapper is found the method lookup is performed. This occurs by taking the wrapper and comapring it with the wrappers in the lookup table of the methods. It will either be a simple hash table of about 16 enties, or a straight linear search through a table. The table will be found through an entry in the method object. If a match is found the corresponding function is invoked with a normal function call, with the exception that the permutation vector for the method is set to the PV indicated in the function header of the method. The method Ufn routine is invoked if a match is not found for the wrapper, where other methods may be searched. - If more than one class is desired, could we xor the wrappers & use that for a hash lookup, then compare each wrapper? Or have a tree structured lookup where the 1st parameter match points off to the 2nd parameter lookup table ... till last match points off to the method. III. Class Lookup Another opcode is desired to return the class (wrapper) of an object. This opcode returns the wrapper of any object. The type bits are used to index into the type table and the indexed value is returned. If the value is 1, then the wrapper should be found at an offset of one from the location pointed to by Tos. If the type table value is NIil, the opcode will trap. The code steps would be something like: - Temp _ ReadMemory[TypeTable + Tos type bits] - Temp = 0 - Yes: Tos _ ReadMemory[Tos + 1] - No: Temp1 = Nil - Yes: Trap - No: Tos _ Temp1 GACHA ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) žIößç‘ÐSf zº