WO1990004829A2 - Object-oriented, logic, and database programming tool - Google Patents
Object-oriented, logic, and database programming tool Download PDFInfo
- Publication number
- WO1990004829A2 WO1990004829A2 PCT/US1989/004687 US8904687W WO9004829A2 WO 1990004829 A2 WO1990004829 A2 WO 1990004829A2 US 8904687 W US8904687 W US 8904687W WO 9004829 A2 WO9004829 A2 WO 9004829A2
- Authority
- WO
- WIPO (PCT)
- Prior art keywords
- objects
- interpreter
- database
- context
- block
- Prior art date
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3664—Environments for testing or debugging software
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F12/00—Accessing, addressing or allocating within memory systems or architectures
- G06F12/02—Addressing or allocation; Relocation
- G06F12/0223—User address space allocation, e.g. contiguous or non contiguous base addressing
- G06F12/023—Free address space management
- G06F12/0253—Garbage collection, i.e. reclamation of unreferenced memory
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/28—Databases characterised by their database models, e.g. relational or object models
- G06F16/289—Object oriented databases
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/20—Software design
- G06F8/24—Object-oriented
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
- G06F8/313—Logic programming, e.g. PROLOG programming language
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y10—TECHNICAL SUBJECTS COVERED BY FORMER USPC
- Y10S—TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y10S707/00—Data processing: database and file management or data structures
- Y10S707/99951—File or database maintenance
- Y10S707/99952—Coherency, e.g. same view to multiple users
- Y10S707/99953—Recoverability
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y10—TECHNICAL SUBJECTS COVERED BY FORMER USPC
- Y10S—TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y10S707/00—Data processing: database and file management or data structures
- Y10S707/99951—File or database maintenance
- Y10S707/99956—File allocation
- Y10S707/99957—Garbage collection
Definitions
- the invention relates to a programming tool that allows application programming in both logic and object-oriented style, and which provides integrated database support Background of the Invention
- Object-oriented programming, logic programming, and database facilities have all been shown to have significant power in the writing of applications to run on a computer. No single programming tool has successfully integrated all three facilities in such a way as to eliminate an explicit interface between them. Normally, one must convert between object data to logic data to use the logic programming system, and then convert the logic data back again in order to use the object-oriented system. Furthermore, one must normally make explicit calls to a database manager in order to retrieve and store application data.
- Gemstone a product of Servio- Logic, Inc., while supporting a database server that can be programmed in Smalltalk, does not allow the application to be written in Smalltalk in such a way that the database server is transparent: i.e. the application must make specific calls to the database server ('Integrating an Object Server with Other Worlds', by Alan Purdy el al, ACM Transactions on Office Information, Vol. 5, Number 1, Jan. 1987). Gemstone does not contain any logic programming tools.
- the present invention solves the problem by providing a single programming tool (referred to herein as Alltalk) which allows the programmer to write applications in an object-oriented language (a dialect of Smalltalk, also referred to herein as Alltalk), a logic programming language, (which is an extension of Prolog, herein called ALF) or a combination of the object and logic programming languages which allows the logic programming language system to consider any object from the object-oriented programming language system as a term in the logic programming language, and which supplies database management on behalf of the programmer, without the need for any specific database management control statements to be supplied by the programmer.
- the main components of the Alltalk tool include a work station having an operator interface, a mass memory, and a CPU.
- An object-oriented programming language system tunning on the work station includes an object-oriented programming language and an object-oriented language compiler for translating, source code written in the object-oriented programming language into objects and interpreter code.
- Also running on the work station is a logic programming system including a logic programming language having components of terms, clauses, predicates, atoms, and logic variables, and a logic language compiler for translating source code written in the logic programming language into objects.
- a database residing in the mass memory stores objects and components of logic programs as objects in a common data structure format, applications data, and applications stored as compiled interpreter code.
- the database is managed by an database manager that represents objects and components of the logic programming language in the common data structure format as objects and is responsive to calls for retrieving and storing objects in the database and for automatically deleting objects from the database when they have become obsolete.
- An interpreter executes the interpreter code and generates calls to the database manager.
- a logic subsystem solves logic queries and treats objects as components of a logic program.
- an improved database format for an object-oriented programming language system.
- the database has a key file and a prime file.
- the prime file contains records of variable length for storing objects
- the key file contains records of fixed length for storing the address, record length, and type of object in the prime file.
- An improved database manager for managing this database includes an object manager employed by the compiler, interpreter, primitives and utilities for providing access to objects in the database, and for maintaining organization of objects in the database.
- An access manager is called by a buffer manager for retrieving objects from the database, a transaction manager for updating the database with new or changed objects at commit points, and for undoing changes to objects upon aborts, and the object manager for providing high level interface to the database.
- a buffer manager is called by the object manager for generating calls to the access manager, and by a pool manager for keeping an in-memory copy of objects. The pool manager maintains memory for buffers.
- an improved garbage collector for a heap based programming language system.
- the garbage collector employs the concept of regions for garbage collection.
- a context representing the state of a method which is executing in the system
- it is assigned a region number.
- an object is created or accessed by a method, it is' assigned the region number of the context of the method that created or accessed it, unless the object was previously assigned a lower number.
- the object is moved to the region of the calling method.
- reference is made from a first object to a second object assigned to another region the second object is moved to the region of the first object.
- the runtime performance of a Smalltalk programming language system is improved by implementing a technique called message flattening.
- the compiler flags any method which consists of a single return statement which returns either an instance variable, or the result of a primitive, for which the first argument is self, and the other arguments correspond to arguments to the method.
- the interpreter detects these flags at runtime and flattens any message that would normally invoke these methods, by replacing this message send in the first instance with an assign, and in the second instance with a primitive invocation.
- Figure 1 is a schematic diagram showing an overview of the invention
- Figure 2 is a schematic diagram of the compiler
- Figure 3 is a schematic diagram of the runtime environment
- Figure 4 is a schematic diagram showing initialized stacks for contexts and block stubs
- Figure 5 is a schematic diagram showing the creation of a new context
- Figure 6 is a schematic diagram showing creation of a block
- Figure 7 is a schematic diagram showing creation of a second block
- Figure 8 is a schematic diagram showing the creation of a new context
- Figure 9 is a schematic diagram showing a block evaluation
- FIGS. 10-13 illustrate the modes of block execution
- Figure 14 shows the creation of a process
- FIG. 15-16 illustrate process management
- Figure 17-18 show the relationships between the context stack, processes, regions, and objects
- Figure 19 is a schematic block diagram illustrating the functions of the garbage collector
- Figure 20 shows the in-use table's structure and internal relationships
- Figure 21 shows the in-use table's relationships with the object table, the buffers, and the database
- Figure 22 shows how garbage is collected upon a method return
- Figure 23 is a schematic block diagram illustrating the functions of the ALF compiler.
- the Alltalk tool runs on workstation type hardware, such as a Sun 4/360 by Sun Microsystems, Inc., executing the UNIX operating system (UNIX is a trademark of AT&T).
- the hardware includes an operator interface including a visual display (CRT) 10, a keyboard 12, and a pointing device 14, such as a 3 button mouse.
- the hardware also includes mass memory, such as a disk 16 on which the Alltalk database resides, as well as a CPU and main memory 18.
- the Alltalk software which is executed by the CPU and main memory 18 consists of an Alltalk compiler 20 for a dialect of the Smalltalk language (also called Alltalk) and an Alltalk runtime environment 22.
- the hardware components of the workstation are connected by a bus 24. 2 Overview
- the Alltalk compiler 20 is a program for translating Alltalk language source statements into interpreter code.
- the compiler is generated by the YACC and LEX utilities in the UNLX operating system, and contains subroutines written in the C programming language.
- the compiler operates in 2 phases: the first phase 26 parses the source code written in the Alltalk language 28 and constructs an intermediate code 30.
- the second phase 32 takes the intermediate code and generates class objects, constant objects, and method objects and places these in a database 40. These objects are subsequently retrieved by the runtime environment 22 (see Fig. 1).
- the runtime environment 22 is written in the C programming language, and in Alltalk.
- the logic language compiler 36 and the logic subsystem 38 are both written in Alltalk. These are compiled through the previously mentioned Alltalk compiler 20, and the output placed in the database 40 and hence available to the runtime environment 22.
- Other applications 42 written in Alltalk are similarly available to the runtime environment after compilation.
- Application programs 42 (called methods) are processed by an interpreter 44, which calls other components of the runtime environment, which includes: a transaction manager 46 which can commit and abort transactions, an object manager 48 which is called to create and retrieve objects, a method fetcher 50 which determines the correct method to execute next, and a garbage collector 52 which detects and removes unneeded objects from main memory.
- the object manager 48 calls upon a buffer manager 54 to determine if a requested object is in memory or needs to be fetched from the database. If the object is to be retrieved from the database, a pool manager 56 is called to find space in an appropriate buffer, after which an access manager 58 is called. It is the access manager 58 that accesses the disk 16 containing the database 40. 3 Compiler
- the Alltalk compiler 20 translates class descriptions written in a dialect of the Smalltalk language herein referred to as Alltalk into database objects for use by the Alltalk interpreter 44 during execution.
- the Alltalk compiler 20 takes a file containing one or more complete Alltalk class descriptions, and for each class generates:
- a class object containing a dictionary of the methods in the class and specification of the instance and class variables
- the Alltalk compiler 20 consists of two phases.
- the first phase 26 (see Fig. 2) does the compilation work, (parse, optimization, and code generation), while the second phase 32 resolves global symbols and loads the results into the database.
- the two phases communicate via intermediate code 30 (written in an assembler-like intermediate language) which can be examined and altered by the user, if desired.
- the first phase 26 of the Alltalk compiler 20 consists of two distinct processing stages:
- the parsing phase is implemented in a fairly straightforward manner using the UNLX yacc/lex parser generator/lexical analyzer tools.
- the primary goal of the parsing stage is to create an internal parse tree representation of the class description and its methods which can be analyzed using a relatively simple set of mutually recursive tree-walking routines.
- the grammer of the input file is checked and errors are reported to the user.
- the grammar specification of the object-oriented language is virtually identical to that specified in the syntax diagrams of the standard Smalltalk language reference, Smalltalk-80 The Language and Its Implementation, by Goldberg and Robson.
- the most notable variation in the Alltalk grammar is that of allowing a primitive invocation to be used as a primary expression and to have primary expressions as arguments, (this is adopted from Little Smalltalk, by Timothy Budd). This allows Alltalk primitives to be intermixed freely with the Alltalk language as if they were function calls which return a value, (which is essentially what the primitives really are), instead of as wholesale replacements for methods, as in standard Smalltalk.
- Additional productions have been included to allow for reading an entire class description from a file, (in a form roughly similar to Smalltalk "fileln/file Out” format). These additional productions include "header” information such as superclass specification, instance/class variable declarations, and instance/class method classification statements.
- the basic parse node is a simple binary node, (left and right child pointers), with placeholders for the node type constant, a source code line number, and a string pointer.
- Parse nodes are created via a function called makenode(), which allocates storage for the node, inserts the current source line number, and sets the other elements as specified by the user.
- makenode() allocates storage for the node, inserts the current source line number, and sets the other elements as specified by the user.
- the storage allocated for these nodes, (as well as for the class and method structures and copies of strings), is not tracked in the Alltalk compiler 20 since the compiler is expected to be run only for the duration of the compilation of a file.
- a sample parse tree for an Alltalk method is given in Table 3.1. Syntactical shorthand and default meanings, such as the return value of a method having no statements being "self', or a block having no statements being “nil”, are fleshed out during the parse phase in order to limit the amount of special case logic in the analysis and generation phase.
- a successful parse generates a parse tree for the statements of each method in the class. These parse trees are anchored in a method structure for each method, which are all, in turn, linked to a single class structure. When the parsing of a class is complete, the class structure is handed to analysis and code generation routines. 3.2.2 Code Generation
- the symbol table is initialized with the instance and class variables available via the superclass chain for the class. These symbols are retrieved from a symbol file in the local directory'. It is considered a fatal error if the superclass cannot be found in the symbol file, (i.e., the superclass must be compiled first).
- Each method is compiled. During method compilation, bytecodes are collected into segments corresponding to groups of statements in the method: one for the method itself, and one for each block within the method. When method compilation is complete, the method code segment is emitted first, followed by the segments for each block.
- the method compilation step is the heart of the compilation task. Before describing this step in detail, a description of the compiler's view of symbolic references and the symbol table is given.
- Block Stub/Closure reference to storage holding
- the symbol table supports a subset of the named references, separating them into the three categories of: 1) class, 2) instance, and 3) temporary symbols.
- Temporary symbols encompass the method parameter, formal method temporary, and block parameter references.
- Global symbol references are never actually placed in the symbol table, but are materialized whenever the search for a name fails. These symbols are resolved by the second phase 32 of the Alltalk compiler 20, since the cross reference values for these names are actually present in the runtime system dictionary contained in the database 40.
- the symbol table interface routines contain the usual routines for the addition of symbols, (add Symbol()), and name-based search for symbols, (find Symbol()).
- An initialization routine, (init Symbols()) purges the table and then uses the globally specified superclass name to populate the table with "ref ' structures for the instance and class variable symbols available via the superclass chain, as recorded in the symbol file in the local directory.
- a routine for writing the instance and class variable symbols, (write Symbols()), to the local symbol file for the globally specified class, (i.e., the one being compiled), is also provided.
- a pair of general routines, (mark Symbols() and release Symbols()) are available for get/set of placeholders in the symbol table. These are primarily used to record the starting position of method and/or block temporary symbols, so that they can be removed at the end of the compilation of the method and/or block statements.
- Block stub/closure id storage for blocks in the method 5.
- a general mechanism for tracking the use of the temporary slots is implemented in the compiler using a set of macro routines.
- This. set includes routines for: allocating a number of temporaries, (alloc Temp()), which returns the starting slot for the requested count; freeing a number of temporaries, (free Temp()); get/set of temporary usage information, (get Temp Use() and set Temp Use()); clearing usage information, (clear Temp Use()); and requesting the high water mark for temporary usage, (maxTemp Use())- Temporary usage is tracked with these routines for the first four kinds of temporaries listed above. Storage for block ids is tallied separately during method code generation since it is not known what the required number of compiler scratch temporaries will be until the method compilation has finished.
- the symbol table is populated with the entries for "self”, “super”, the parameters, and the formal temporaries.
- the slot index for each entry is determined by allocating a temporary as each symbol is added to the table.
- a code segment is allocated for the method statements and made to be the "active" segment.
- generated code is placed in the "active" code segment, which is switched when compilation of a new list of statements, (e.g., a block), is started or completed.
- Label generation is reset, (used for branch targets and block entry points).
- Method flattening is a technique for determining whether a runtime message send can be avoided because the method is "trivial".
- a "trivial" method is one which contains a single statement returning either:
- compile Statement List() with a pointer to the first statement parse node of the method. This routine invokes compile Expr() to compile the expression associated with each statement in the list.
- Compile Statement List() is used to compile lists of statements for blocks as well as methods, generating appropriate return bytecodes when explicit return statements are encountered and after the last statement in the method or block.
- Expression compilation is the center of most activity during the compilation of a method.
- Compile Expr() defines the compilation actions for all parse nodes other than statements in a concise manner. This routine is invoked with the node to be compiled and a destination specification for the result of compiling the expression indicated by the node in the form of a "ref" structure.
- the destination specification allows the calling routine to control placement of the expression's value, which is particularly useful for aligning values for message sends, minimizing unnecessary data movement at runtime.
- Simple expressions, such as identifiers and constants are trivial compilations requiring only assignment of the value associated with the identifier or constant description to the specified destination.
- An explicit Alltalk assignment expression (e.g., "a ⁇ - b + c"), only requires compilation of the expression on the right of the " ⁇ -", with the reference on the left as the destination, in addition to assigning this result into the specified destination for the assignment expression itself, (e.g., "d ⁇ - (a ⁇ - b + c)"), if indicated.
- the remaining expression types (messages, cascades, primitive invocations and blocks), require somewhat more involved compilation steps, hence, these cases have been split into separate routines, (gen- Send(), gen Cascade(), gen Exec Prim(), and gen Block()). We now describe the compilation steps performed in each of these cases.
- the runtime implementation of the send message bytecode requires that the receiver and arguments be present in a contiguous set of the sending context's temporaries.
- the location for the return value of the message send is also required to be a temporary in the sending context, though it need not be adjacent to the receiver and arguments.
- Gen Send() complies with the first condition by allocating a contiguous set of temporaries, (via alloc- Temp()), and compiling the receiver and argument expressions with each of these temporaries, (in order), as the specified destination. Hence, results of receiver and argument expressions are cleanly aligned with their use in containing message sends, eliminating unnecessary data re-positioning assignments. A simple optimization is also done at this point. If the receiver and argument temporaries already happen to line up, (detected by lineup()), new temporaries are not allocated and the receiver and argument values need not be moved.
- the second condition (destination must be a temporary), is honored by examining the specified destination reference and allocating a temporary to hold the result of the message send if the destination is not already a temporary. This situation is remembered and code is generated for moving the result from the allocated temporary to the actual destination after the message send.
- This implementation style allows for the addition of variations of the send message bytecode for non-temporary destinations, if the need arises.
- Alltalk's primitive invocations require that arguments to the primitive be in a contiguous set of the invoking context's temporaries, and the destination for the result be a temporary in the invoking context
- Gen Exec Prim() handles the non-temporary destination and argument alignment cases, (using lineup()), in the same manner as is done for message sends.
- Each primitive argument is compiled, allowing arbitrary expressions to be used as arguments.
- Blocks are the most involved expression compilations in that they cause changes in the global state of the compiler.
- a block is a list of statements which are to be executed with their own context when a "value" message is sent to it.
- the lexical aspects of a block allow it to refer to names available to the method in which the block is defined, as well as to names in any containing block. These names include the method's parameters and formal temporaries and any containing block's parameters.
- These semantics imply that a block is a static "object" of sorts which can potentially have multiple runtime activations, with each activation dynamically establishing variable name ⁇ -> storage bindings.
- a block is a separate list of statements to be compiled and "set-up" as an object, which may also include cross-context runtime references to be represented.
- Gen Block() alters the global state of the compiler to create the proper compilation conditions to meet the needs described above.
- the block being compiled is given a unique id within the method, and a new code segment is allocated and marked with this id and connected to the list of code segments generated for the method so far.
- the currently active code segment is saved, along with its temporary usage, (since the block will have its own context), and the new segment is made the active segment (generated code is always placed in the active segment).
- the previous code segment and its temporary usage are restored when compilation of the block is completed.
- the symbol table is marked so that the block's symbols, (block parameter names), can be released at the end of the block's compilation, and the block's symbols are added to symbol table for proper scoping. Finally, a label is generated to mark the start of the block's code in the method.
- the information associated with the block stub id is used to establish a context for executing the statements of the associated block whenever the "value" message is sent to this id, (i.e., the evaluate block bytecode is executed for the id). Note that this requires that a block must be “set up” before it can be “evaluated” at runtime.
- the solution to the placement problem is to group the set up block bytecodes for any "top level” block, (i.e., any block encountered while generating code for the method statements), and its contained blocks, and place them in the method code segment ahead of the the first use of the "top level” block.
- This technique avoids executing set ups for any block(s) which are not in the specific control flow path at runtime.
- Gen Block() implements this strategy by setting a pointer to a position in the method segment code at which the set up block bytecodes are to be "spliced" when a "top level” block is entered.
- Opt While() handles optimization of the various "while" messages which can be sent to blocks, (while True:, while False:, while True, and while False). This routine demonstrates the need to deal with:
- Opi Block() determines the code generation strategy based on the type of the parse node representing the block in the parse tree. If the node represents a literal block in the source code, the statement list for the block is compiled into the active code segment using compile Statement List()- Otherwise, a "value" unary message expression, with the node representing the block as the receiver, is constructed and compiled under the explicit assumption that the receiver will be a block, (gen Eval- Block()). Note that this assumption is not made, (and a different bytecode is generated), when the "value" message is encountered in the original source code, since the actual receiver may not be a block at runtime, in this case.
- Literal blocks which are part of the "while” message may be “top level” blocks, (i.e., outermost block of a nesting within a method). Because of this, opt While() must set the "splice point" in the method segment code for set up block bytecodes for any blocks contained in the "while” blocks, such that these bytecodes are placed outside the looping portion of the "while” code. This avoids the multiple "set up” problem for a block discussed in the previous section on block compilation.
- the intermediate language expected as input for this phase consists of tokens representing bytecodes, along with directives for establishing the class, delimiting methods, and tracking the Alltalk source file name and line numbers.
- tokens representing bytecodes along with directives for establishing the class, delimiting methods, and tracking the Alltalk source file name and line numbers.
- directives for establishing the class are listed in Tables 3.4 and 3.5, respectively.
- phase 2 translates both the source and destination effective address forms into one of six specific runtime reference types.
- Phase 2 maintains a global state around the current class and method being "assembled", resulting in method-at-a-time assembly and placement into the database.
- the class object is not given to the object manager until all methods described in the input file have been successfully translated and passed to the object manager. This insures that the old version of the class, (hence, its methods), is not replaced unless assembly of the new version is successful.
- phase 1 In contrast to phase 1, this phase is very "flat", that is, it contains no recursive functions to walk parse trees, since each input statement is essentially a self-contained description. All the implementing functions, (assembled), are dispatched directly from the parser on a per statement, (or group of statements), basis, resulting in a very simple control flow.
- Assembly of a method essentially consists of collecting the bytecodes described by the bytecode statements into a scratch area, (Method Bytes), and recording labels, references to labels, and block references in these statements for resolution when the end of the method is reached.
- Each bytecode statement has a corresponding translation routine, (assembles), which builds the runtime representation of the bytecode in the scratch area.
- end Method() When the end of the method is reached, (end Method()). all label and block references are resolved and the object manager is called upon to allocate space for the compiled method object. In this area, the instance variable slots for the method object are initialized, (no Temps, no Parms, class Oop, selector Symbol, .... etc.), and the bytecodes are copied in from the scratch area.
- a dictionary entry relating the method selector symbol id of the method to the id of the compiled method object is also created and added to entries already established for other methods, (in the Methods global array). These dictionary entries are stored in the class object when the end of the class is reached, (i.e., when a new '.class' directive or end-of-file is encountered).
- end Class() space is obtained from the object manager under the same object id as the previous version of the class, to cause replacement of that class.
- the class is then built in this area by filling in control information, including the object id of the first instance of the class obtained from previous version, the object id of the class name symbol, the id of the superclass and the size of the method dictionary for the class.
- the method dictionary entries are then closed-hashed, (by method selector symbol id), into a dictionary area in the class object.
- the class object is then flushed to the database, signaling completion of the assembly of the class, ending phase 2.
- the interpreter 44 (see Fig. 3) is that portion of the Alltalk runtime environment 22 which the user invokes to run Alltalk applications.
- the interpreter 44 decodes the object code generated by the compiler 20 (see Fig. 2), and executes it calling upon many of the other services of the runtime environment 22.
- the interpreter 44 also includes a debugger, described below, which allows the programmer to inspect the running program in a variety of ways.
- the previously described Alltalk compiler 20 for the Alltalk dialect of the Smalltalk language translates Alltalk source code into an intermediate representation, called bytecodes, and stores this representation in the database 40.
- Each bytecode represents an instruction for the interpreter 44, and consists of an operation code (a 32 bit integer) and a variable number of parameters.
- Applications are executed using the Alltalk interpreter 44.
- the Alltalk interpreter 44 uses the object manager 48 as the interface to the database 40. It also calls on the transaction manager 46 and the garbage collector 52. In addition, it invokes primitives which interface to the UNIX operating system to do things like operating on primitive data types (integer addition, floating point multiplication, string concatenation, etc.), performing file I/O, managing the display, and controlling keyboard and mouse input
- the object manager 48, transaction manager 46, garbage collector 52, and primitives are described in later sections in more detail.
- the state of the Alltalk interpreter 44 is captured, essentially, in a global array called Processes. Each element of this array represents one Smalltalk process.
- One process is created.
- the user's application can create new processes, switch processes, and destroy processes as- needed
- Associated with each process is a stack of contexts, and a pointer to one which is the currently-executing context of that process.
- a context is created when a message is sent or a block is evaluated, and is destroyed when the corresponding message/block returns.
- Associated with each context is a set of bytecodes for the corresponding method/block, and a pointer to one which is the currently- executing bytecode of that context
- the bytecodes are the object code to which the user's appbcation was compiled.
- Each context also has an array of temporaries which are used to hold intermediate results of the execution of the associated method/block.
- the current context of that process is, then, the current context
- the current bytecode of that context is the current bytecode.
- the basic operation of the Alltalk interpreter 44 is a bytecode decode/dispatch loop. Code exists in the interpreter for handling each type of bytecode generated by the compiler. The interpreter decodes a bytecode to determine its type, then invokes the appropriate code for that bytecode type. We call the piece of code for a particular bytecode type a bytecode handler. Each bytecode handler increments the bytecode pointer so that after the handler completes, the interpreter main loop can decode and dispatch the next bytecode. Bytecode handlers can manipulate the bytecode pointer and other interpreter data structures in ways to affect program flow.
- the routine exec_bcodes() contains the bytecode loop. It decodes the bytecodes and invokes the appropriate bytecode handler. Before doing so, however, it checks to see if it should switch processes, i.e., it checks whether a different Smalltalk process should become the currently-active process. See the section below on Process Management for details on how process switches are handled and new processes are created.
- Each handler is one (or more) case(s) in a C-language switch statement.
- the switch statement is part of exec_bcodes() in the file exec_bcodes.c.
- Each case of the switch is in a separate file to make source code maintenance easier.
- these files are included in exec_bcodes.c via #include's. This strategy was chosen over making the bytecode handlers each separate procedures because it cuts down on call overhead in the bytecode loop. It also allows the use of machine registers for certain control variables, since the handlers are all within a single C language function. Note that thousands of bytecodes are executed each second; overhead for that many calls would be very large.
- the bytecodes can be grouped into the following categories:
- Primitives are called by Alltalk code to do the low-level tasks. These tasks generally depend on the underlying hardware and operating system, and include things like file I/O, integer and floating point arithmetic, and using the display. The bytecodes numbered from 0 to 255 (decimal), i.e., 00 to FF hex, are reserved for primitives. Primitives are similar to methods in that they have a receiver, they have optional arguments, and they return an object They are unlike methods in that they are written in C rather than Alltalk, and no context is set up for them. 4.3.2 Send a message
- the compiler generates several different types of bytecodes for messages.
- the normal message send is handled by send_msg_bcode.
- Messages of the type 'perform:' and 'perform:with:' are handled by send_param_ nsg_bcode.
- send_msg_bcode the message selector is known at compile time, and is included in the bytecode itself; for send_param_msg_bcode, the oop of the message selector is found, at run time, in a temporary of the current context.
- send_msg and send_param_msg
- blocks are not objects managed by the object manager, but rather are maintained by the interpreter as C data structures.
- instance variables or returned as the result of a message, they are made into objects, is the home context (this is discussed in more detail below). They can, however, be assigned to method temporaries and passed as parameters in messages without being made into objects first
- a setup_blk bytecode When the interpreter encounters a setup_blk bytecode, it creates a data structure called a block stub, and gives it an object id (which is a 32 bit integer) which we call an oop).
- the oop is in a special range, i.e., greater than or equal to INIT_CNTX_ID, so it can be recognized later as a block by the interpreter.
- the block stub contains enough information to evaluate the block when an eval_blk bytecode is later encountered. Its oop is stored back in the temporaries of the home meth od in which it is defined. It can then be handled like any other oop stored in temporaries (except for the cases mentioned above).
- Evaluating a block means executing the code that the block contains. Note that a block must be 'set up' before it can be evaluated However, a block which is set up may or may not be evaluated. For example, the if True: block and if False: block of an if True:if False: message won't both be evaluated. A block may be evaluated immediately after it gets set up, or later. It may be evaluated by the context in which it was set up, or the context which sets it up may pass it as a parameter in a message send, so that it gets evaluated by another context.
- the eval_blk bytecode handler causes a block to be evaluated by converting the block stub for that block into an active context on the context stack of the active process. It makes that new context be the current context, and makes the global bytecode pointer point to the block's first bytecode. 4.3.5 Return from a block or method
- Alltalk interpreter 44 When the Alltalk interpreter 44 encounters a return bytecode, it means that the currently executing context is finished, and it switches control to a previous context In addition, it passes back an object (actually the object's oop) to the context to which it is returning.
- a short return causes the interpreter to return to the context just previous to the current context regardless of what it is.
- a short return and a long return from a method context are the same. (The Alltalk compiler 20 always generates a long return for returns from a method context)
- a short return from a block means to simply return to the previous context in the stack. This previous context is the context which caused the block to be evaluated; it may or may not be the block's home context
- Branch bytecodes are used to implement control structures. In addition, branching bytecodes are used by the compiler as part of several optimizations.
- the unconditional branch bytecode (0x105) simply increments/decrements the bytecode pointer by a certain amount.
- the conditional branch bytecodes compare an oop found in a temporary of the current context with an oop contained in the bytecode itself. Whether or not the bytecode pointer is incremented depends on the results of comparing these two oops.
- the Alltalk compiler 20 and the Alltalk interpreter 44 understand six different types of variables. These six types are as follows:
- This type of variable is simply an oop that the Alltalk compiler 20 generates, and includes as part of the assignment bytecode. Obviously, it cannot be the destination of an assignment statement, only the source.
- Type 1 variables are string, character, integer, and floating point constants, and class names.
- This type of variable is a temporary in the home context of the current context
- the Alltalk compiler 20 specifies it as an index into the array of temporaries.
- This type of variable is an instance variable of the object which is 'self in the current context.
- the Alltalk compiler 20 specifies it as an index into the instance variables of the receiver.
- This type of variable is an indirect reference to a particular instance variable of a particular object.
- the Alltalk compiler 20 specifies the instance variable by specifying an index into the temporaries of the current context (which specifies the object), plus an index into the instance variables of that object (which specifies the particular instance variable).
- This type of variable is a temporary in the current context.
- the Alltalk compiler 20 specifies it as an index into the array of temporaries. Note the difference between this and the type 2 variable.
- type 2 and type 5 are the same because a method's home context is itself; for a block, type 2 refers to its home context's temporaries, and type 5 refers to its own temporaries.
- This type of variable is needed for nested blocks in which an inner block refers to an argument of an outer block.
- the Alltalk compiler 20 specifies the argument by giving two parameters in the bytecode. First is an index into the temporaries of the home context. In that particular temporary is found the id of me block stub of the outer block. The second parameter is an index into the temporaries of the outer block. In that particular temporary is found tiie oop of interest Since Smalltalk does not allow assignment to the arguments of a block, a type 6 variable cannot be the destination of an assignment statement, only the source.
- Each assignment bytecode has a source variable type and a destination variable type. The destination is specified first, then the source. Because type 1 and type 6 variables cannot be destinations, there are 24 assignment bytecodes (4 destination types * 6 source types). The assignment bytecode handlers simply put the oop specified by the source into the location specified by the destination. 4.4 Context Management
- the state of the Alltalk interpreter 44 is contained in the global array, Processes. Each element in that array represents a process. In addition to the interpreter's C-language data structure for a process, there is also an instance of Smalltalk Class Process for each Smalltalk process in an application. In the following, we concentrate on the interpreter's data structure for processes, and ignore the Smalltalk object. Each process has associated with it a set of contexts. In the following, we explain how contexts are implemented for one process, but one should remember that there is one set of contexts for each process.
- Alltalk interpreter 44 In order to improve performance of the Alltalk interpreter 44, it does not treat contexts as objects. Instead, they are maintained by the interpreter as C data structures. (As mentioned above, however, the home context may be turned into an object if an owned block is turned into an object).
- the Alltalk interpreter 44 manages contexts in two pieces.
- One piece contains what are called active contexts. These are contexts associated with methods which have not yet returned and blocks which are executing and have not yet returned. This piece operates like a stack: when a message is sent or a block starts execution, the Alltalk interpreter 44 pushes anottier context on the stack; when a method or block returns, the Alltalk interpreter 44 pops one context (or more, in the case of a long return from a block) off the stack.
- the second piece contains what are called block stubs.
- a block stub is established as the result of a setup_blk bytecode (see setup_blk_bcode).
- object id's (oops) are given to such blocks.
- the block stubs represent these pseudo-objects. They hold just enough information so that when a block is evaluated (a value message is sent to it), the Alltalk interpreter 44 can create an active context for it Note that a block stub exists as long as its home context exists; it does not go away just because its associated active context returns. In fact in the case of loops in Smalltalk code, the same block stub might be evaluated many times, having an active context created from it and destroyed each time.
- block stubs are stored as a separate piece, the active contexts can be allowed to obey a stack discipline. This simplifies context management and improves performance.
- Contexts are of fixed size, and have 64 temporaries each. (Smalltalk defines 64 as the maximum number of temporaries a context may have.) This allows the Alltalk interpreter 44 to allocate space for them and doubly link them at interpreter initialization time, rather than on the fly. They are allocated as an array, and have one array/stack of contexts per Smalltalk process.
- the routine init_cntx() initializes one context and it is called by init_cntx_stack() which initializes and links all contexts for a given process when the process gets created.
- Block stubs are of fixed size. This allows space to be allocated for them and allows them to be linked at interpreter initialization time, rather man on the fly. They are allocated as an array, and have one array/stack of contexts per Smalltalk process.
- the routine init_blk_stub_stack() initializes and links all block stubs for a given process when the process gets created
- the Alltalk interpreter 44 maintains a pointer to the current active context, cur_cntx, and a pointer to the next available (unused) block stub, next_blk_stub, for each process.
- Each context has a prev pointer which links it to the previous context in the array/stack, and a next pointer which links it to the next context in the array/stack. These pointers are used rather than the array index to move between contexts.
- the Alltalk interpreter 44 follows the next pointer of the current context when it needs to add a new context This happens when a message is sent (see send_msg_bcode), or a block is evaluated (see eval_blk_bcode).
- the Alltalk interpreter 44 follows the prev pointer of the home context of the current context to find the context to which it should return when it does a long return; it follows the prev pointer of the current context itself when it does a short return (see “short return", Table 4.1).
- home_cntx points to itself.
- home_cntx points to the context of the method in which the block is defined. This pointer is needed when the Alltalk interpreter 44 does long returns from blocks, and when blocks refer to the temporaries of their home method. By having a method context's home be itself, the Alltalk interpreter 44 can handle all long returns (both from method contexts and from block contexts) in the same way.
- the first_block field of a context points to the first block stub that the context could allocate.
- my_blk_stub is not used, and is NULL.
- the field points to the context's corresponding stub. This pointer is used by the debugger (described below), and is also used in conjunction with the prev_active_cntx field to handle the case where one block stub has multiple active contexts at the same time.
- prev_active_cntx is not used, and is NULL.
- it is used in conjunction with the my_blk_stub field to handle the case where one block stub has multiple active contexts at the same time. It saves a pointer to the previous active block context associated with this block context's block stub. If this context is the only active context associated with the block stub, then this field holds a NULL pointer.
- Each block has an id which is an oop (long integer) in a special range, that is, greater than or equal to the constant INIT_CNTX_ID.
- the id's are assigned to a stub when the process to which it belongs is initialized.
- the id can be stored in the temporaries of other contexts, and can be passed as a parameter in a message send. In this way, blocks can be treated (almost) like real objects for flexibility, and yet be managed by the interpreter for good performance.
- Each block stub has a next pointer which finks it to the next block stub on the array/stack.
- the Alltalk interpreter 44 uses the one pointed to by the global pointer, nex ⁇ _blk_stub. At that time, it follows the next pointer of the stub pointed to by next_blk_stub to update next_blk_stub.
- Each block stub has a pointer to its home context. If the stub gets evaluated, the Alltalk interpreter 44 needs this pointer in the active context created for the block. Via this pointer, it can get at the temporaries of the home context
- the Alltalk interpreter 44 updates the stub with a pointer to the active context that gets created to do the evaluation. This pointer is needed in order to resolve references to type 6 variables.
- the Alltalk interpreter 44 When a block is stored in an instance variable, or passed back from a method the Alltalk interpreter 44 must make the block a persistent object In so doing, it must also make the home context a persistent object as well, since the block can reference temporaries of the home context Alltalk contains routines to make the block and its home context persistent objects (and thus they may then be stored in the database and manipulated as any other object), and to put the block and home context back on the stack so that the block can be executed.
- Figures 4 through 13 show how context management is done in Alltalk.
- Each Figure shows the same portion of the active context stack and the block stub stack for one process.
- Each box in the Figures represents one context or one stub; only the fields involved in context management are shown. (The my_blk_stub and prev_active_cntx fields are shown only in Figure 13.)
- Pointers are indicated by arrows; pointers "connected to ground” represent NULL pointers. Pointers shown in double lines indicate pointers which were changed from the previous figure. The stacks grow downward.
- Figure 4 shows the state of the two stacks after the interpreter has been initialized, but no messages have been sent Note that the next and prev pointers of the contexts, and the next pointers of the stubs have been established. Also, the id's of the stubs have been set.
- Figure 5 shows what happens when a message is sent. (We assume that the sending context is just off the top of the figure; the context we are about to create is the top box we see in the figure.) We follow the next pointer of the sending context to "create" a new context (from here on, called method context #1). The new context becomes the cur_cntx, and its class is Method Context. Since it's a method context, its home_cntx is made to point to itself.
- next_blk_stub Its first_block pointer is made to point to the stub pointed to by next_blk_stub. Note that next_blk_stub is not moved; only when a block stub is used (i.e., set up) is the next_blk_stub moved forward.
- Figure 6 shows the stacks after method context #1 sets up its first block.
- Setting up a block means that the Alltalk interpreter 44 created a block stub; it does not mean that the Alltalk interpreter 44 creates another active context.
- the block stub pointed to by next_blk_stub becomes the new block stub.
- the Alltalk interpreter 44 pushes next_blk_stub forward to the stub pointed to by the next field of the new block stub.
- the home_cntx field of the new block stub is made to point to the home_cntx of cur_cntx, i.e., method context #1. Note that if cur_cntx were a block context, the home_cntx of the new block stub would not be that block context but rather the block's home context. Note also that method context #1 does not change.
- Figure 7 shows what the stacks look like after method context #1 sets up another block. We now have two block stubs whose home_cntx is method context #1.
- Figure 8 shows the stacks after method context #1 sends a message.
- the Alltalk interpreter 44 must "create” a new context (from here on, called method context #2).
- the Alltalk interpreter 44 follows the next pointer of the current context to find the next available active context, and make it the cur_cntx. Its first_block pointer is made to point to the block stub pointed to by next_blk_stub. Since the new context is a method context, its home_cntx field is made to point to itself.
- Figure 9 is somewhat more complicated. In that figure, we see the stacks after method context #2 starts to evaluate one of the blocks that was set up by method context #1. (We assume that the block was passed as a parameter in the message which resulted in the creation of method context #2.)
- the stub to be evaluated is #214740009.
- the Alltalk interpreter 44 must "create" a new active context - but this time, it is a block context. Just as with method context creation, the Alltalk interpreter 44 follows the next pointer of the cur_cntx to find the next available active context and make it the cur_cntx. Also, the Alltalk interpreter 44 makes its first_block pointer point to the block stub pointed to by next_blk_stub.
- the home_cntx pointer of the new context does not point to the new context itself; because the new context is a block context, its home_cntx pointer is gotten from its block stub. In this case, home_cntx points to method context #1.
- the block stub's active_cntx pointer is made to point to the new block context The transformation of a block stub to an active context is handled by the routine stub_to_cntx().
- Figure 10 shows how the stacks would appear if the block were to do a short return.
- the Alltalk interpreter 44 simply follows the prev pointer of the current context to find the context to return to; it is made me cur_cntx.
- the block stub associated with the evaluated block does not go away, even though its active context did go away. Block stubs go away when their home context goes away (returns).
- the Alltalk interpreter 44 also moves next_blk_stub to point to the block context's first_block. This effectively "destroys" and frees up any block stubs set up by the block context. (In this case, the block context created no block stubs, so next_blk_stub does not change.)
- Figure 11 shows how the stacks would appear if the block were to do a long return.
- the block's home context is method context #1, so the Alltalk interpreter 44 (in essence) does a return from method context #1. It follows the prev pointer of method context #1 to find the context to return to; it becomes the cur_cntx. It also moves the next_blk_stub pointer back to point to the stub pointed to by first_block of method context #1. This effectively "destroys" and frees up all blocks created by method context #1 and any of its descendent contexts.
- Figures 12 and 13 show how the my_blk_stub and prev_active_cntx fields are used to handle the case where a block stub may have multiple active contexts associated with it Note that these fields are shown in these figures only, and only for block contexts. Note also that we have shifted our view of the stacks down (or up) by one context in order to fit the contexts of interest on the page.
- Figure 12 shows how the stacks would appear if a second block context was activated for the same block stub as the current context. Note that the two block contexts created from the same block stub are very similar; only their prev_active_cntx fields differ. Note th at the second one uses this field to point back to the previous (first) one. Note also th at the active_cntx field in the stub is updated so it points to the new context
- Figure 13 shows how the stacks would appear if the second block context did a short return.
- the Alltalk interpreter 44 follows the my_blk_stub pointer of the returning block context to find its associated block stub. It copies the prev_active_cntx pointer of the returning block context into the active_cntx field of the stub. Then it does the normal processing for a short return, that is, follow the returning context's prev pointer to find me sending context and makes it the new current context.
- prev and prev_active_cntx point to the same context, that is, the first block context; however, this will not necessarily be the case. There could be other intervening contexts between these two activations of the same stub. This is why it must save this information in the newly-created context.
- the Alltalk interpreter 44 maintains run time data structures for Smalltalk processes in an array called Processes[]. Each element in that array represents one Smalltalk process. Each element contains (basically) a stack of active contexts, a pointer to the current context in that stack, an array of block stubs, and a pointer to the next available stub. The management of these two stacks and two pointers was described in the previous section. However, we have not yet discussed how processes are created, switched, or destroyed. These topics will be discused in this section.
- a Smalltalk process is created by sending a message to a block.
- the block contains the code thai is to be executed in the new process.
- the message sent to the block might be fork At:, fork, etc. However, all of th ese messages eventually result in the message new Process being sent to the block.
- the Smalltalk code for method new Process in Class Block is shown in Table 4.2.
- the routine create Process() is the main routine for creating a new process. It first finds an available element in the Processes[] array by calling get_proc_id(). Then, in order to create a new process in Alltalk, the Alltalk interpreter 44 establlshes the first context in that new process. It does that by copying appropriate active contexts and block stubs from the creator process to the created (new) process, and then making slight adjustments to the copies. This is best explained using an example.
- the Alltalk interpreter 44 copies the user's block and its home context (see proc_copy_cntxl() ), plus the outer block and its home context (see proc_copy_cntx2() ). After that, it evaluates th e outer block, that is, it creates an active context from the block stub. When the new process becomes active, this, in turn, causes the user's block to be evaluated (as a result of the message self value). When that block finishes, the new process is destroyed (as a result of the message Processor terminate Active).
- Figures 14 through 16 illustrate the relationships between these contexts and blocks.
- Figure 14 shows a portion of the active context stack and block stub stack of the creator process.
- the contexts and stubs shown are the ones that are of interest when the Alltalk interpreter 44 creates the new process.
- Figure 15 shows me active context stack and block stub stack of the created process just after it is created by the interpreter.
- Figure 16 shows the same stack just after the new process has become active, and the user's block begins to execute.
- the machinery for managing process switches is contained in the module process.c. It follows the implementation described in the standard reference for Smalltalk by Golberg and Robson, mentioned above. 4.5.3 Destroying Processes
- Destroying i.e., terminating
- a process involves two basic steps. First, the appropriate element of the Processes[] array is marked as not in use so it can be reused if needed. Second, the garbage collector (described below) is told to clean up after the process. The routine destroy Process() handles these two tasks.
- Processes are destroyed in two situations.
- the first case is when the interpreter quits. At that time, all active processes are destroyed so garbage collection can be performed correcdy.
- the second case is when a terminate message is sent to a Process object. This second case is implemented via primitives. Note that process 0 is created automatically when the interpreter is initialized; it cannot be destroyed, except by shutting down the interpreter. 4.6 Optimizations
- the Alltalk interpreter 44 detects at runtime if a message send's only purpose is either of the following 2 cases:
- the Alltalk compiler 20 flags methods that are of these types, for easy detection at runtime.
- the Alltalk interpreter 44 will execute the appropriate logic in-line, and modify flags in the bytecode that is being executed, as well as caching in the bytecode itself the class of the receiver. Subsequent executions of the bytecode involved will cause the class of the now current receiver to be checked against the class cached in the bytecode. If it matches, the Alltalk interpreter 44 performs the optimized logic, in-line, without fetching (or executing) the method. Thus this optimization saves the fetching of the method, allocation (and subsequent deallocation) of a new context and interpretation of the method.
- Rath er than have one bytecode just for dispatching primitives, (e.g, an execute_primitive bytecode), in Alltalk, each primitive is its own bytecode. This eliminates the extra level of indirection to get to the code for primitives.
- primitive bytecodes are in the range of 0x000 to 0x0FF hex; other bytecodes begin at 0x100.
- the Alltalk interpreter 44 avoids the call to the object manager to fetch the receiver again. Instead, since in Alltalk a pointer to the receiver is held in the associated context, the Alltalk interpreter 44 gets the receiver pointer from the associated context instead.
- the Alltalk interpreter 44 attempts to' replace send_msg_bcodes with eval_blk_bcodes when possible.
- the Alltalk compiler 20 recognizes messages with the selector value (and value:, etc.), and replaces them with eval_blk_bcode2 bytecodes. This bytecode is the same as the eval_blk_bcode, except that it must check to see that the "receiver" of the value message is a block.
- eval_blk_bcode2 simply returns, and lets processing fall through to the next bytecode which is a send_msgJbcode for the value message; if the receiver is a block, eval_blk_bcode2 operates like evalJblk_bcode, except tiiat it must push the bytecode pointer past the following send_ msg_bcode which it replaces. 4.6.5 Caching methods in send_msg bytecodes
- Alltalk uses a performance-improving technique, common to most Smalltalk implementations, known as method caching.
- the technique takes advantage of the fact that while Smalltalk allows polymorphism, a given message often ends up being resolved to the same method every time. How Alltalk takes advantage of this is as follows.
- the send_msg bytecode has two extra fields which implement a method cache.
- One field is likely_class. This saves the class of the receiver of the message when it was last sent
- the second field is likely_method. This saves the oop of the compiled meth od to which the message was resolved last time it was sent
- the Alltalk interpreter 44 checks to see if the new receiver's class matches likely_class; if it does, it uses the compiled method in likely_method. If the classes do not match, it must do the normal, more expensive processing to fetch the appropriate method.
- the Alltalk interpreter 44 calls the object manager to reserve the method object, to insure the object is not garbage collected until the object is no longer needed. However, this is less expensive than normal method fetching. Note also, that if the cache is not usable (i.e., the receiver's class does not match likely_class), the Alltalk interpreter 44 updates the cache to match the receiver's class and the method's oop in the current message.
- Alltalk interpreter 44 The main procedure of the Alltalk interpreter 44 is contained in the module interp.c. It performs various types of initializations, then invokes the bytecode loop by calllng exec_bcodes(). When exec_bcodes() returns, main() does some minor clean up, and exits.
- Command line arguments are processed. These are parameters passed on the statement used to invoke the runtime environment 22. They include switches for relinquishing control of the keyboard and mouse to the Smalltalk application, and for avoiding the normal system booting procedures. Another parameter is an optional filename; it indicates tiiat the interpreter should get the information for the initial message of the application from that file rather than by prompting the user.
- the object manager 48 is initialized via a call to init_om().
- the oops of certain Alltalk objects are referenced in the Alltalk interpreter 44 via global variables.. Some of th ese are fixed to certain oops. For example, true is always oop 257. However some of the oops referenced via interpreter globals must be determined at start up of the interpreter - they are not fixed forever, just for the duration of the interpreter's run. The appropriate assignments are made by calling initialize Oops(). Likewise, certain instance variable indices are referenced by the interpreter via globals. These, too, must be determined at start up. A call to initializelndices() takes care of this.
- the bytecodes and context for the first message are built and made the first one to be executed.
- the interpreter 44 builds: a) send_msg and return bytecodes for the message startup sent to Class System Boot;
- the debugger is named RAID, and it combines many of the features of the standard Smalltalk debugger and the UNTX debugger, dbx.
- RAID Revised Alltalk Interactive Debugger
- Alltalk system We designed it to be used for debugging both Alltalk applications code, and the Alltalk system (implementation) itself.
- RAID provides typical debugger capabilities such as:
- RAID is written in C, and is integrated quite closely with the Alltalk interpreter.
- the user interface is a simple command interpreter, that looks somewhat like the Unix debugger, dbx, to the user.
- the command interpreter uses UNIX utilities lex and yacc to parse input and dispatch the appropriate C routines that perform the tasks of the RAID commands.
- Alltalk interpreter 44 There are several versions of the Alltalk interpreter 44 , each geared to a particular need. Not all of these interpreters contain RAID. For example, one version is optimized for running debugged applications as fast as possible; leaving out the debugger improves performance considerably. Another version is geared toward the collection of performance statistics; it also does not include the debugger. The version of the interpreter built by default, however, does include RAID.
- One piece is a set of C routines in a library separate from the interpreter, that performs the tasks associated with the RAID commands.
- Each command has a C procedure associated with it and th at procedure may use oth er utility procedures to do its work.
- This first piece is conditionally linked to the interpreter depending on which version of the interpreter is made.
- a second piece is the code within the interpreter that can get conditionally compiled into the interpreter itself; by default, it is included, but it can be excluded if debugging is not needed. This code is included when the C compiler switch DEBUGGER is on.
- the third piece is a set of global variables and constants th at are used to communicate between the first two pieces.
- piece one simply as the debugger; piece two will be referred to as RAID code in the interpreter, piece three will be called debugger globals.
- RAID is invoked when the interpreter calls a routine in the debugger called, appropriately enough, debugger().
- Flow of control is as follows: 1) RAID code in the interpreter calls debugger().
- debugger() prompts me user, and invokes the lex/yacc command interpreter.
- the command interpreter parses and interprets the user input, and calls the appropriate C- procedure with the appropriate parameters.
- the C-procedure performs the tasks associated with the desired command. This usually results in either display of some information (like the contents of the current context), or the updating of the debugger globals (like turning on or off the switch that tells the interpreter to stop at the next message-send).
- RAID code within the interpreter may call debugger() (step 1 above); it may update debugger globals; or it may display data to the user based on the values of the debugger globals (switches).
- the interactive interface to RAID is a simple command interpreter built using the UNIX utilities lex and yacc.
- the utility lex defines what are valid tokens in the RAID "command language"; the grammar defines how these tokens can legally be put together to form commands.
- the grammar calls the C- procedure associated with the command, passing the command parameters as arguments.
- Tokens representing command names are all uppercase, e.g., MSG_STEP.
- Oth er terminals have first letter uppercase, all others lowercase, e.g. Hex_numeric.
- Non-terminals are all lowercase, e.g., help_param.
- RAID global constants are all uppercase, e.g., D_PROMPT_SYMBOL.
- RAID typedefs and structure definitions are all lowercase, e.g., d_ostat_struct.
- RAID global variables have first letter uppercase, all otiiers lowercase, e.g., D_init_vals. 4) RAID macros are all uppercase, e.g., D_CRESET().
- RAID procedures are all lowercase, e.g., d_where().
- Some operations of RAH are controlled by two sets of binary switches.
- One set of switches controls the trace information that is displayed as the interpreter runs, e.g., message sends and returns.
- the other set holds state information, e.g., which RAID command is currently executing.
- Each set of switches is implemented using a global variable bit vector, plus three macros: one for setting a particular switch (bit), one for resetting a particular switch (bit), and one for testing whether or not a switch (bit) is set.
- the first set of switches uses the global variable D_display_switches, and the corresponding macros are D_DSET(), D_DRESET(), and D_ISDSET().
- the second set of switches uses the global variable D_control_switches, and the corresponding macros are D_CSET(), D_CRESET(), and D_ISCSET().
- debugger() This command simply continues execution of the interpreter by causing debugger() to do a return.
- debugger() to return by setting the global variable D_in_debugger to "0" (zero). quit, restart, rerun
- the quit command causes the interpreter to exit; restart aborts the current Alltalk apphcation, restarts the interpreter on the same application, and gives a RAID prompt; rerun is equivalent to restart followed immediately by a continue - it does not re-prompt the user before restarting the application. It is important to do garbage collection before aborting an application, so these commands make sure each active Smalltalk process is explicitly destroyed before aborting.
- the code does different tilings depending on the state of the Alltalk interpreter 44 when the command is invoked.
- the user is forced to get into the bytecode loop (by executing one bytecode, for example) before allowing any of the tiiese commands to be used.
- the debugger does longjmp() to an appropriate spot in exec_bcodes() where all active processes are destroyed in order to- be sure garbage collection is done appropriately. Then it returns to interp().
- the debugger sets the appropriate global switch (D_QUIT, D_RERUN, or D_RESTART) so that when it returns to interp, it knows whether to exit, restart, or rerun. run
- the run command is similar to restart, but it is used when the user wants to run a different Alltalk application without leaving the interpreter.
- the code then, must clear all breakpoints (since these are probably not meaningful in the new application), and get new values for the interpreter's initial message. 4.8.4.4 Commands for finding out where you are print_message, where
- the where command is analogous to the dbx command of the same name. It prints out the currently active messages, i.e., the messages sends that have not yet returned. Only those messages in the currently-active process are printed
- the print_message command prints only the most-recendy activated (last sent) message. Both commands use the routine d_print_msg() to print the message associated with a given context; where calls this routine on all the contexts in the context stack of the current process; print_message calls this routine only on the current context
- This command handles a stop set for a particular bytecode type, e.g., send_msg_bcode. If the user enters the command without a parameter, the. debugger simply prints out the currently-set stop, if any. If a parameter is given, the debugger stores it into the RAID global variable, D_stop_at_bcode. Bytecodes range from (hex) 0x100 to 0x156; primitives range from (decimal) 0 to 255. The user may specify a bytecode in either range. As the interpreter executes, within exec_bcodes(), before executing a bytecode, it checks the bytecode against the D_stop_at_bcode; if it matches, the interpreter calls debugger(). stop_in, delete
- Stops are stored in the global array D_stop_in_data. They are identified by number, from 1 to D_MAX_STOPS.
- the parameters of the stop_in command define a new stop; new stops are added using d_add_stop() called from d_stop_in().
- stop_at if invoked witii no parameters, stop_in simply prints the currently set stops using d_print_stop(); Stops are deleted using the delete command. Note that deleted stops cannot be re-used.
- send_msg bytecode handler After each send_msg bytecode is executed, a check is made to see if the just-executed bytecode matches any of the stops. If so, the stop is printed, and debugger() is called.
- This command simply causes the interpreter to continue execution until the next bytecode is about to be executed. It sets the D_BCODE_STEP switch. During interpreter execution, before a bytecode is executed in exec_bcodes(), this switch is tested; if set, debugger() is called. The switch is reset every time debugger() is called. goto, skip_msg
- This command is to messages as bcode _step is to bytecodes. It causes the interpreter to continue execution until the next message is sent It sets the D_MSG_STEP switch. During interpreter execution, after a send_msg bytecode is executed, this switch is tested; if set debugger() is called. The switch is reset every time debugger() is called. next_msg
- This command is rather more compllcated than msg_step.
- This command is to msg_step as the dbx command next is to the dbx command step. That is, it causes the interpreter to continue executing until the next message at the current level is sent In order to do th is, it must keep track of what the current level was when the command was invoked; this is stored in D_base_cntx.
- the interpreter executes a send_msg bytecode, it checks to see if the message just sent was sent from D_base_cntx. If so, then debugger() is called. Also, on every return bytecode, the interpreter checks to see if it is returning from (or past) D_base_cntx. If so, D_base_cntx is set to be the context to which it is returning, the user is given a warning message, and debugger() is called. This is analogous to doing a next in dbx past a return. return
- This command causes the interpreter to continue execution until it returns from (or past) the current context.
- d_return() sets the D_RETURN flag, and fills in the global D_ret_from with the current context and process id.
- ret_bcode checks these; if D_RETURN is set and it is returning from or past the context specified in D_retj ⁇ om, the interpreter displays a message and calls debugger().
- This simple logic gets complicated because of the optimization that converts message sends into assign54 bytecodes and primitive bytecodes. Note that the user is unaware of these optimizations, so the interpreter makes tiiese optimizations transparent to her.
- the interpreter uses the switches D_MSG_REPLACED and D_RET_FROM_REPLACED_MSG to keep track of these situations.
- the set and unset commands turn on and off, respectively, the various display switches. See the section above on how these switches are implemented. How each of the switches is used is described next set/unset bcode
- the D_BCODES switch is tested in exec_bcodes() before the interpreter executes each bytecode. If the switch is set it calls print_bcode() on the bytecode about to be executed. set/unset context
- the D_CONTEXTS switch is tested in exec_bcodes() after the interpreter executes each bytecode. If the switch is set, it calls d_print_cntx() on the current context. set/unset block
- the D_BLOCKS switch is tested by the interpreter when a block is evaluated If the switch is set, the debugger prints information about the block that the interpreter is about to evaluate. The switch is also tested when the interpreter does a return. If the switch is set, and it is returning from a block, the value returned is displayed. Note that this information is not printed if the debugger is currendy executing a nextjnessage command, and the interpreter is at a level below the level at which the next_message command was invoked. set/unset process
- the D_MESSAGES switch is tested when a message is sent. If the switch is set the debugger prints information about the message that the interpreter is about to send. The switch is also tested when the interpreter does a return. If the switch is set, and the interpreter is returning from a message (rather than from a block), the value returned is displayed by the debugger. Note that this information is not printed if the debugger is currently executing a next_message command, and the interpreter is at a level below the level at which the nextjnessage command was invoked. Also note mat the interpreter takes care of the cases in which a message send is replaced by a primitive or an assign54 bytecode. The assign54 case is handled in send_msg_bcode; the primitive case is handled in send _msg_bcode (for the send) and exec_prim_bcode (for the return). set/unset receiver
- the D_RECEIVERS switch is tested in exec_bcodes() after the interpreter executes each bytecode. If the switch is set, the debugger calls d_print_receiver() on the current receiver.
- the print_global command takes a string as a parameter; it's used for objects such as symbols, Class names, and other global objects.
- the print_oop command takes an oop (integer) as a parameter.
- the print _receiver command takes no parameter; it simply causes the debugger to print the contents of the current receiver. print_temp
- This command lakes a small positive integer as parameter.
- the parameter corresponds to a method temporary of the currently executing method; 1 represents the first temporary, 2 the second, etc.
- the routine d_print_temp _num() calculates where to find this in the temporaries of the appropriate context on the stack, and prints it as an oop.
- print_bcode is a general routine, which is also used by the database lister. print_active_cntx, print_bIock_stub, print_cntx_of _stub
- the interpreter maintains contexts, one for each currently-active message and block, in an array, one array per Smalltalk process.
- the interpreter also maintains an array (one for each Smalltalk process) for each block that has been set up and is active or has the potential to become active (we call these block stubs). These commands allow the user to print the contents of any of these contexts or block stubs.
- the command print_active_cntx takes as a parameter a positive integer which is the index into the array of contexts of the current process. That particular context is printed using d_print_cntx().
- the command print_block_stub takes as a parameter a block stub id. This is a positive integer greater than INIT_CNTX_ID. This range of integers is used to track blocks independently of normal objects.
- the routine d_p rint_block_stub() translates this id into an index into the array of block stubs for the current process; the appropriate block stub is then printed.
- the command print_cntx_of_stub also takes a block stub id as parameter. As with print_block_stub, it finds the appropriate stub; but it uses d_print_cntx() to print the active context associated with that stub, if there is one. print_process
- This command causes the debugger to print the contents of the interpreter data structure associated with a particular Smalltalk process, not including the context stack or the block stub stack. status
- This command is equivalent to executing the following commands, all without parameters:
- stop jn prints method stops, if any
- stop_at prints bytecode stop, if any
- stat_status prints statistics collections that are turned on, if any
- Alltalk A tool for collecting statistics on Alltalk messages is implemented in Alltalk. This tool is invoked from within RAID. Basically, it keeps track of which methods are executed, how many times each is executed, and how much time is spent on behalf of each method and its descendants.
- D_stat_tab The other is a stack of records, one record for each message which is active, i.e., has been sent but has not yet returned. There is one stack per Smalltalk process, and th ese are stored in the global array, D_stat_stack. When a method returns, its record is popped from the stack, and 'added' to the table.
- a stack record is defined by struct msg_rec. It contains the class and selector of the method; this is used to identify the method. It also contains the class and selector of the method which invoked it.
- the stack record also contains two pairs of the following form: a time stamp, and a cumulative time. One stamp/cum pair is used to keep track of time spent on behalf of th is meth od and its descendants; the other stamp/cum pair keeps track of time spent in the method only.
- the statistics tool stores in the start_time sub-field the time at which the method begins executing. When the method returns, it subtracts start_time from the current time, and store the result in the elap_ti me sub-field.
- the statistics tool stores in the time_stamp sub-field the time at which the method begins executing.
- time_stamp is subtracted from the current time, added to the cum_time sub-field which is initally zero.
- time_stamp is reset.
- time_stamp is again subtracted from the current time, and result added to cum_time. In this way, cumjime keeps track of only the time spent on behalf of this method, exclusive of its descendants.
- the stats table is an array of records. Each record is of the type struct method _rec. A record contains a class and selector to identify its method, plus the number of times it has been sent (and returned), plus the total time spent on its behalf, plus the total time spent on behalf of it and its descendants. When a meth od returns, the routine shown in table 4.5 is performed.
- the command stat_on turns on collection of statistics; stat_off turns off collection. This is done by setting and resetting the switch, D_STAT. This switch is tested by send_msg_bcode (and send_param_msg_bcode) and ret_bcode; if the switch is set, these routines cause statistics collection to be done. Neither command affects the table, but both initialize (empty) the stack.
- the command stat_reset initializes the stack and empties the table. Any statistics collected up to this point are lost.
- the table can be printed to the screen or to a file using the stat_print command, and one can determine whether or not statistics collection is on by using the stat_status command.
- the statistics tool also includes a means for collecting statistics related to the object manager 48.
- the statistics collected are mainly counts of various events, and maximum and minimum values of certain object manager variables/sizes.
- the statistics tool uses two instances (D_ostats and D_obuffer_cnts) of one large structure (d_ostat_struct) to keep various statistics.
- the collection of object manager statistics can be turned on and off at any time via RAID commands.
- commands are available for printing object manager statistics to the screen or to a file; for resetting the collection 'table'; and for determining whether or not collection is turned on or off.
- RAID has an on-line help facility.
- the user enters the help command with a command name as a parameter, he is presented with a manual page (a la UNIX) for that command.
- the help files are written in UNIX nroff form.
- the debugger uses the system() UNIX library routine to invoke the UNIX more command on the appropriate help file.
- the grammar translates the parameter (the command name) from a string to a token (i.e., constant) before passing it on to the d_help() routine.
- the d_help() routine then does a switch based on that constant and displays the correct file.
- Invoking the help command witiiout a parameter results in the display of a summary of all commands. Invoking the short_help command (takes no parameters) causes an even shorter list of all the commands to be displayed.
- the object manager 48 provides access to objects in the database 40 and in main memory 18. It is used by the compiler 20, interpreter 44, primitives, and utilities. It maintains the database 40 as well as the organization of objects in memory. Object manager 48 is also called by the method-fetcher 50 to fetch methods for the interpreter 44, using the class of the receiver of a message, and the Smalltalk superclass hierarchy. Although the object manager 48 is described herein with reference to the Alltalk tool, the object manager 48 is also useful as a general purpose object-oriented database manager.
- the database 40 consists of 2 UNIX files: db Jcey and db.prime.
- the key file provides associative access to the prime file: the access manager 58 hashes into the key file (all of whose records are of fixed length), and finds the address (file offset) of the object in the prime file.
- the key file record also contains the length of the prime record, so the access manager 58 knows how many bytes to retrieve.
- Objects in the prime file are 1 of 6 types: OBJ_REC, a normal Alltalk object as seen by the Alltalk programmer; SYMBOL_XREF, a symbol cross-reference record th at contains the string for the symbol and the associated oop of the Alltalk symbol object; and DICT_XREF, which is the Smalltalk dictionary cross-reference record
- This dictionary record contains the string that is the name of the global symbol (e.g. Class name), the oop of the associated Alltalk symbol object as well as the object id of the Alltalk object th at has that symbol as the object's global name.
- the oth er types are CTL_REC, the control record; CKPT_REC, the checkpoint integrity record; and DLT_REC, a logically deleted object record.
- the key file is divided into 2 parts, an objectKey Space, and a symboI Space.
- the object Key Space part of the file (which is first in the file) is used to find the address of an object, given the oop (object id).
- the second pan of the file, symboI Space is used to find a cross-reference record, given the string associated with a symbol or global.
- the access manager 58 To use the symboI Space, the access manager 58 hashes the string to get an address in symboI Space, retrieves the key record at that address, and then proceeds to the prime file to retrieve the cross-reference record, which contains the oop of the object being sought
- the records in the key file are of fixed length, and contain three fields:
- ColUsions in the key file are handled by chaining the objects in the prime file together. If the object at the address indicated by the key file record does not have an id (oop, or string) tiiat matches the target sought the access manager 58 follows the 'overflow' chain in the records in the prime file, checking the target against the id until it is found. Fastest access to newest objects is provided by placing them first in the overflow chain. 5.2 Database access manager
- the routines in the access manager 58 are called mainly by the buffer manager 54 (when objects are to be retrieved), and by the garbage collector 52 and the transaction manager 46 (when objects are to be added/updated in the database at commit points). They are also called by dictionary and symbol access routines discussed later.
- control record is stored as the first record in the prime file. This contains the next available oop (to use for new objects), and the next available address in the prime file (used and then updated when new records are added to the prime file).
- the control record also maintains certain database statistics, including the last checkpoint id. It is written to the database after every commit is complete, to insure proper restart
- the first call to the access routines will open the Unix files, and put a (UNIX) lock on the files, to assure single user access.
- the lock check can be overridden for read-only access (as in the database-lister utility).
- the checkpoint integrity record is also checked by the access manager 58 to make sure that the system was not aborted while a 'commit' was in progress. This record is updated in the database with the checkpoint id when the commit starts. If the first call to the access manager finds the checkpoint id in the control record out of sync with the checkpoint id in the checkpoint integrity record, the access manager 58 aborts (the control record is written to the database only after the commit is successful). The only way to recover is to restore from a back-up
- the fetchit function retrieves an object from the database 40, given a record type and a key.
- the fetched record is placed in the buffers (see buffer manager, below), along with the disk address of the retrieved record. This will be used if/when the record needs to be replaced in the database.
- the storeit function is capable of adding a new object (or replacing same) in the database.
- First the access manager 58 looks at the record's disk address (which was stored with the record in the buffer, when (if) the record was previously retrieved). If th is is not NULL, it knows that the record already exists in the database, and it replaces the record using this disk address (records never change their disk address during a run, except when they are lengthened -- see below). The responsible program must NULL out this address if the record has changed its key, or if the record has lengthened. If the access manager 58 cannot use the disk address, it assumes it has a new record.
- the access manager 58 fetches the record pointed to by the key, updates the new record's overflow pointer to point to the record currently pointed to by the key record, and then updates the key record to point to the new record being added. This insures that fastest access is to newest records (they are first in the overflow chain).
- the forceit function will put a record in the database, but (unlike storeit) checks to see if it is already there. If so, it logically deletes the old copy and adds the new one.
- This function is called when an object is newly created with an oop dial already exists (e.g. a Class), and when an object is lengthened. It uses the storeit function if the new object is not already in the database, or is smaller than the one it is replacing. Else, the access manager 58 gets the old object and logically deletes it (by placing a special mark in the recjype), and then executes the storeit logic.
- CaUers of the access methods are expected to have determined the id of the object even if it is a new one. They can call oop_gen to get the next available id. This routine will look at a table (filled in by the garbage collector 52, when an object is deleted) in an attempt to reuse oops. If none are available for reuse (e.g. at start of run), the access manager 58 creates a new one by using and then incrementing a field in the control record tiiat keeps track of the next oop to create.
- the function start _commit is called when a commit is started (normally in the transaction manager). This routine updates the special checkpoint integrity record mentioned above. If the run is aborted before the commit is finished the control record will be out of sync with the checkpoint integrity record, causing subsequent runs to be aborted.
- Chckpt_oop is called when a commit is finished. Presumably, the calling program called start _commit and has now finished writing all of the changed objects to the database (via storeit and forceit), and the database is now in sync with memory. Chckpt_oop will update the control record indicating the commit is finished, and write it to the database. The control record also keeps track of the next oop to use, and the next prime file address to use.
- the buffer manager 54 maintains the in-memory copy of objects. It is caUed by the object manager 48 when an existing object is to be fetched or when a new object is to be stored in the buffers. It can be called with the following operations:
- buffer manager returns an error if it finds it there), and the object is to be fetched from the database and put in the buffers.
- the buffers are updated with the new (version of the) object
- New space in the buffer is allocated, the object's disk address is set to zeros (the disk address is control data kept with the object in the buffer), and the object table is updated to point to the new spot in the buffer where the new version of the object will be stored.
- the buffer manager 54 uses an object table to keep track of which objects are already in the buffers.
- the table contains the id and a pointer to each object in the buffers.
- To retrieve an object the buffer manager hashes into the object table to see if it is already in memory. If not, the object is fetched from the database, placed it in the buffer, and the object table is updated.
- the buffer manager 54 needs space in the buffers in which to place a new object, a "forced" object, or an object from the database, it calls upon the pool manager 56 to find the space in the correct buffer. In any case, the buffer manager 54 returns a pointer to the object to the calling program.
- the pool manager 56 maintains memory for the various buffers. It keeps a total of 7 buffers: small slot, medium slot and large slot buffers for methods, another set of 3 for non-method objects, and one buffer, "huge", for oversize objects (methods and non-methods can both go in “huge”). Except for the "huge” buffer, all buffers have fixed size slots. Memory for the buffers is pre-allocated, except for "huge", which is maintained using the UNIX routines: malloc/free.
- Pool manager is called to find a spot in a buffer for an object. It uses the size and type (method/non- method) of the object to determine which buffer to search for the empty slot If a slot is found, a pointer to the slot is returned to the calling program (probably buffer manager 54). It searches for an available slot with the following algoridim. 1. For each buffer a "slot-indicator" is kept which is the next slot to look at This is maintained across calls to pool manager, and wraps around when the end of the particular buffer is encountered. It is updated to be one higher than the slot returned the last time the pool manager found space in that buffer.
- Two searches of the buffer are made, starting at the slot-indicator.
- a search is made for a slot that is empty, or else holds an object that is not being used (i.e., not in the "in- use” table, -- see garbage collector section), and whose "usage Count" is 0.
- This usage Count is incremented every time the object manager 48 fetches the object and decremented every time the pool manager 56 looks at the object's slot; it indicates the frequency of access to the object If a slot can not be found on the first pass, the usage Count is ignored on the second pass. If a slot cannot be found on the second pass, it means the buffer is filled with objects that are being held by the interpreter 44, and the run must be stopped (memory is exhausted).
- the object table is updated by removing the entry for the object in the buffer slot that is about to be reused, and an entry in the table is added for the new object just placed in the buffer.
- the number of slots and the slot size can be tailored to fit the distribution of object sizes in the database. Alltalk runs faster with fixed size slots in each buffer, since this means that no compaction is required by the garbage collector 52. Different buffers are provided for methods vs. other objects because non-mediods are expected to be more volatile in their usage than methods, and to have a different size distribution. 5.5 High Level Object Manager Protocol
- the object manager 48 provides a set of high-level functions for object access. It is these functions that are used by the interpreter 44, compiler 20, primitives, and others.
- the access manager 58, pool manager 56, and buffer manager 54 are used to implement these higher level functions.
- a program can call the object manager 48 with a call of NEW in order to establish a new object in memory.
- the class id of the new object must be supplied.
- the object manager 48 will fetch the class of the new object, and initialize the new object appropriately.
- the caller must also supply the number of index variables required. The latter parameter can not be changed for the object later: to "grow" an existing object the FORCE call must be used.
- the FORCE call will accept the id of the object to be grown, and set up a new object with the specified quantity of index variables. It is up to the calhng program (usually a primitive) to set all oth er data appropriately.
- Reserve_obj will fetch a requested object, and lock its position in memory until the current method (and all other users) ends. This is done by putting an entry in the "in-use" table for the process and region that is passed in the call to reserve _obj.
- This table is described in the garbage collector section; it serves to keep track of which objects have their memory address pinned down (until the the garbage collector processes the region specified). The entry does not leave the table until the object is either garbage coUected, or, if updated, written to the database. It is the presence of this entry that keeps the pool manager from re-using the object's slot in the buffer.
- the reserve_obj routine must be used if the caller expects to eitiier update the object, or re-access the object using the pointer returned from the call.
- the other retrieval routine is get_obj which also returns a memory pointer to the object requested.
- This routine will not guarantee that the pointer is valid across calls to the object manager routines. It is used mainly by primitives where only temporary, read-only, access is required.
- the object manager requires that no calling program cache object pointers except in the interpreter contexts. It also assumes that no program is maintaining local storage of object id's except the interpreter context temporaries, and instance variables of other objects.
- the reason for these restrictions is that the garbage collector only knows which objects are referenced through the instance variables of other objects (and context temporaries), and only knows which objects have their addresses cached by having entries in the in-use table; all other objects are fair game to be garbage collected.
- the entries in the in_use table are tagged with the region id (see the garbage collector), and it is assumed that when the region is collected, the memory pointers are no longer required, and the object's buffer space can then be used for other objects.
- the object manager logic also depends on the calling program setting the UPDATE flag in the object if the object has been updated. This is the only indication that the object is to be (eventually) re-written to the database. If an object is to be made permanent in the database (even though it has no references from oth er object's instance variables), the calling program should call "referenced" to establish this (see the garbage collector section). An updated object's storage in the buffers will not be re-used until after the next commit call. This is assured by an entry being placed in the in-use table for the object, when reserve_obj was called
- New objects and existing objects that have been updated are written to the database when the transaction manager is called to do a commit or when the garbage collector collects region 0 of a process (see the garbage collector section). This latter event happens whenever a process terminates, and at end of run.
- an object is written to the database, its UPDATE flag is turned off and (if it is not otherwise pinned down), the pool manager can consider its slot in the buffer for reuse.
- Routines getdictionary and putdictionary update the Smalltalk dictionary, and retrieve an object given a global name (a string). Similarly, getsymbol and putsymbol
- the method fetcher 50 retrieves the appropriate compiled meth od object given a selector, the receiver's class, whether it is a "send super", and whether the message is to a class or an instance object. It fetches the class and looks up the selector in the dictionary. If not found, it fetches the class's class, and so forth. Normally, it stops in class Object but continues on if the original message was to a class. In this case, it follows the metaclass chain, as described in the standard Smalltalk reference. The method fetcher 50 employs a table to retain the method id, given a selector, class, and meth od type. It examines this table first before chasing the superclass chain. 6. Garbage Collector
- Garbage is defined as objects tiiat are no longer reachable, and therefore can be safely discarded. Since there is no explicit delete command available to the programmer in a Smalltalk language, removal of objects is entirely up to the system. Furthermore, since many objects are transient in an Alltalk session, it is important that the objects be collected efficiently with a minimum of disruption to response time.
- the garbage collector 52 is described in connection with the Alltalk tool, it is useful for garbage collection in any heap based language system (such as Lisp, Prolog, and a variety of object-oriented languages, such as Loops, and Flavors).
- the garbage collector 52 is integrated with the object manager 48 and interpreter 44.
- the garbage collector 52 shown in more detail in Figure 19, includes a collector means 200 for implementing the actual garbage collection function, a region cleaner 202 for detecting regions that have accumulated an excess number of objects, and caUing the collector 200 to clean such regions; a cross-process checker 204 for insuring that no object in-use by another process is discarded; and an off-line mark/sweep collector 206 called by the interpreter for periodically removing objects from the database 40 that have become unreachable (directiy or indirectly) by any object in the database dictionary.
- the collector 200 employs an in-use table 101 described below, in executing the garbage collection function.
- a process is a Smalltalk object representing a light-weight thread of control. Multiple processes may exist, but only one is active at any time. Processes in Alltalk adhere to the definition in the standard Smalltalk reference.
- a context is a Smalltalk object representing the state of a method which is executing.
- Contexts are analogous to stack frames in procedural languages, with the notable exception that allocation/deallocation does not always obey a strict stack discipline.
- Regions are not Smalltalk objects. They are used in Alltalk for garbage collection. In Alltalk, each context belongs to a region. Several contexts from the same process may belong to the same region, but a context is associated with only one region, and regions do not span processes. When a context is created, it is assigned a region number. Once assigned, a context's region number, never changes. Each object created or accessed is assigned the region number of the context that created or accessed it, unless it was already associated with a region with a lower number. After the number of objects in the 'current' region exceeds a fixed maximum, a new region (with an id one greater than the previous one) is started when the next context is created.
- Figure 17 shows a context stack for processes 0 and 1.
- the first two contexts 60 and 62 within the context stack 64 for process 0 belong to the same region (0).
- the next two contexts 66 and 68 in the stack belong to different regions (1 and 2), and the last two contexts 69 and 70 in the stack 64 are assigned to the same region number (3).
- the stacks for each process grow in the direction of arrow A, by adding contexts to the tops of the stacks.
- Figure 18 shows how objects belong to both regions and processes. For example, object 72 belongs to both process 0, region 0, and to process 1, region 1.
- Object 74 belongs only to process 0 region 0.
- Object 76 belongs only to process 1 region 1.
- object A refers to object B via one of its instance variables
- A the parent of B
- B the child of A.
- the in-use table 101 in Alltalk keeps track of those objects in memory which must not be overwritten and whose location in memory must not be changed. Typically, such objects fall into one of the following categories.
- the interpreter 44 retrieves the receiver of a message send, and caches a pointer to it in the corresponding context Until the context returns, this pointer must remain valid
- any number of method executions may be suspended waiting for the return of a message send.
- Objects created or updated as the result of the execution of such a method may have to be kept in the in-use table until the method returns. They cannot be written to the database, because they may turn out to be garbage (i.e., created only to hold temporary results). This determination can only be made after the method finishes executing.
- the object manager 48 makes one entry in the in-use table for each object that needs to be kept in memory. If an object is referenced from multiple processes, it will have multiple entries, one for each process. However, if an object is referenced multiple times from the same process, it has only one entry for those references.
- Figure 20 shows the format of entries in the in-use table 101. An entry has the following fields:
- a pointer to the object in memory (buffer pointer);
- Entries 100-110 in the in-use table 101 are chained together in two ways. First all entries for a given object (e.g. object A, 112, entries 100-104) are chained across processes. In this way, the garbage collector 52 keeps track of the fact that an object may be referenced from more than one process. Additionally, all entries for a given process are chained across objects. For example, entries 106 -110 are all for process 0. This chain connects objects from tail to head, in order from highest region to lowest, for a given process. This allows the garbage collector 52 to scan all objects within a process from high regions to low regions, in order to collect (discard) unused objects efficiently. 6.2 Assigning objects to regions.
- Objects are put into the in-use table by the object manager, and assigned to regions by the garbage collector as follows: (Note that when when an object is 'moved' to another region, it is not physically moved; its region field in the in-use table changed).
- Figure 21 shows how the in-use table 101, the object table 120, an object in the buffers 122, and the key file 124 and the prime file 126 of the database 40 are all related.
- the object manager Given an object's id (oop) 128, the object manager hashes the oop to find the entry in the object table 120, and follows the pointer 134 to determine its location in memory (the buffers 122).
- the object in the buffer 122 has a header portion which is used only by the object manager; it is not visible to the interpreter, and it does not get written to the database 40.
- this header contains a pointer 130 back to the object's entry in the object table 120, and a pointer 132 to the object's first entry in the in-use table 101.
- Figure 21 also shows how the object address in the key file 124 points to the location of the object in the prime file 126 of database 40.
- the object manager cannot find the object in the object table 122, it retrieves the object from the database. It hashes the object's id 128 to access the key file, which contains the actual disk address 140 in the prime file 126 in the database 40.
- Case 2 shows a context in region n+1 returning to one in region n. Since n+1 is not two larger than n, no action is taken.
- Case 3 shows a context in region n+2 returning to one in region n. Since n+2 is twolarger than n, the collector 200 collects regions n+2 and n+1, and all oth er regions having numbergreater than n.
- a region is collected by following the chain of objects in the in-use table for the current process. Starting at the tail of the chain, entries are removed until an entry is reached belonging to the region of the context to which the process is returning. When an entry is removed, a check to see if it is the only entry in the table for that object (by checking the cross-process/by-object chain for the object).
- the collector 52 goes to its header in memory, and null out its pointer to the in-use table.
- the pool manager 56 then knows that slot can be re-used. If the pool manager 56 decides to reuse the slot it follows the back pointer to the object's entry in the object table, and deletes that entry.
- the region cleaner 202 detects this and the collector 200 "cleans" the region(s) involved. To detect that a region needs to be cleaned, the region cleaner 202 keeps track (by region) of the number of objects accumulated since the last "region cleaning". When this exceeds a certain maximum point (e.g., 150 objects), the region cleaner 202 invokes the collector 200 for the region involved. The number of objects in one of the regions is checked every time any new object is created. The region that is checked is the "next" one, which is that region in the same process that has a region number that is 1 higher than that of the region that was checked upon the previous object creation.
- regions are ordered by process number, and th en region number widiin process.
- the next to be checked will be region 0 of the process with a process number that is 1 higher than the previous one that was checked.
- the "next" region to be checked is set to be region 0, widiin process 0.
- the region cleaner is a procedure that looks at the region to be cleaned, and all regions with region numbers less than this, within the same process. All updated database objects, and all objects pointed to by the interpreter contexts (within the same process/regions) are marked via direct memory pointers (i.e. receivers and method objects). Then the transitive closure of all objects pointed to by marked objects is marked. However, any object tiiat is not in memory, or not in a region being cleaned, or that is neither a newly created nor an updated object is not marked. These restrictions limit the number of objects examined during the mark/sweep, and keep the mark/sweep entirely within main memory so that no disk accesses occur.
- the interpreter 44 When the interpreter 44 establishes a new process, it knows which (non-global) objects from the spawning process are being shared with the new process. Upon creation of the new process, the interpreter asks the object manager 48 to place entries for each shared object in the in-use table, at the new process id. The object manager will create entries for the object and its transitive closure at the new process.
- any object shared between 2 or more processes has entries for each process in the in-use table, and so do objects reachable from the shared object (children, etc). All entries for a single object, (used in multiple processes) are linked together, so it is easy to determine which processes share a given object.
- the collector will not discard any object if it is in use by another process: when the region for a process is collected, all entries in the in-use table are removed for that process, but the object is not removed from the object table, nor is its space reclaimed, until there are no more processes sharing the object
- the cross process checker 204 checks to see if the new parent (P) is in use at multiple processes. If it is, the child C (and its children, etc), have entries placed in the in-use table for whatever other processes also share the parent, that do not already share the child (etc). The child is placed in the same region that owns the parent (for the process). This logic is in addition to the region checking between parent and child mentioned above.
- Objects are not written to the database 40 unless they are reachable (at commit time) by some object in the database.
- An off-line mark/sweep collector 206 is run periodically to remove objects from the database that have subsequently become unreachable. The same utility removes logically deleted objects and re-organizes the database for efficiency.
- Certain objects set up by the compiler are outside the mark/sweep logic: these are mainly constants compiled into meth ods. These constants are not 'reachable' in the normal way, and instead, have a flag ("PERMANENT OBJECT") set, that cause mark/sweep to treat these as already "marked”.
- Other examples of permanent objects are symbol objects for selectors established by the compiler or other symbol objects pointed to from the global dictionary. The only way to get rid of these is to completely rebuild the database. This is not a problem, if applications avoid putting data in the global dictionary, but instead use regular Smalltalk dictionaries (pointed to by the global dictionary).
- the mark phase reads the database sequentially. It skips over any (already) marked objects, non- permanent objects, and logically deleted objects (the latter objects are explained in the object manager description above).
- the remaining unmarked permanent objects are processed by:
- Classes have their method dictionary entries placed in the kids table as well to insure that the method objects will be marked.
- the mark phase processes all of the children in the "kids" table first (fetching these from the database, and if they are not already marked: marking them, putting their keys in the reorg file, and adding their children to the kids table). It can be seen that the records placed on the reorg file are in "children depth first", which will cluster parents and their immediate children together.
- Each record is processed as follows: 1. Fetch the object indicated by the reorg record, from the (old) database. If the fetched object is not a class object place the id of the last object processed for the class of the object in the fetched object's class chain (this keeps a pointer chain between all objects of the same class). Store away the fetched object's id for use in updating the class chain of the next object, of the same class, that is processed during this phase.
- step 2. Write the object fetched in step 1. to the new database at the next available byte (i.e., the objects are packed together in the order encountered on the reorg file).
- the mark/sweep collector 206 updates all of the classes with the first instance of that class (head of class chain), to anchor the class instance chain.
- the sweep phase (like the mark phase) keeps various statistics and does integrity checking as it goes along, and reports them out at the end.
- region 0 of a process When region 0 of a process is collected, that process has ended and all objects created by tiiat process, that are reachable from the database, are written to the database by the garbage collector 52. To accomplish this, the collector will signal that a commit is in process, and then write out all objects to the database that remain in the process (all have been moved to region 0 by tins time), and which cannot be garbage collected Any object that is also shared by another process is not written out, since this will be taken care of when that other process terminates. Note that the shared object could be garbage collected between the time when one sharing process terminates, and the otiier sharing process terminates. Not writing the object out when the first process terminates results in fewer "garbage" objects being written to the database.
- a commit routine flushes objects to the database that are reachable from database objects.
- An abort routine invalidates all objects in the buffers which have been updated or created since the last commit. This forces subsequent accesses to tiiese objects to be fetched from the database, and thus effectively "backs out” any changes since the last commit
- ALF the Alltalk Logic Facility, which gives the Smalltalk programmer logic programming capabilities, integrated in a natural way with the object-oriented programming paradigm.
- ALF stands for both the programming language (which is an extension to Prolog), and the runtime logic used to maintain, compile, and execute ALF programs.
- ALF is written entirely in Alltalk, and runs under the Alltalk system like any other application. Facilities are provided to compile logic programming statements, to group them into programs, and to submit logic queries against ALF programs. All of these features can be invoked from any Alltalk program and answers to queries can be subsequentiy used in Alltalk programs. Since ALF is implemented in the Alltalk system, ALF also provides permanence for its objects, i.e., rules, facts and queries.
- the ALF language is similar to the LOGIN language developed by Hassan Ait-Kaci and Roger Nasr, which in turn is an extension to Prolog.
- ALF differs from LOGIN in some details of syntax, and in its integration with the Smalltalk language. Both ALF and LOGIN generalize unification by taking into account a lattice relationship among types, which in the case of ALF is the Smalltalk class hierarchy. Both ALF and LOGIN also generalizes the syntax for terms to allow "attribute labels", which for ALF are taken as identical to the Smalltalk (names of) instance variables.
- ALF statements are made up of clauses, which have a head, followed by an arrow, followed by a tail.
- the head is a single atom
- the tail is a list of atoms separated by commas.
- Clauses with botii a head and a tail are called rules, those with only a head are called facts, and those with only a tail are caUed queries, as in standard Prolog terminology.
- atoms are comprised of predicate symbols with arguments (called terms). The terms are named (unlike Prolog) rather than being positional, and (again, unlike Prolog) can be typed. The type is indicated by the name of a Smalltalk class, and the type itself can be further qualified by giving additional term values for the type class (and these may again by typed, and so on, indefinitely).
- Hearty, Healthy, and Less Than are all the names of (Smalltalk) subclasses of class Predicate.
- Hearty and Healthy have at least one instance variable called thing. It may be that there are other instance variables in Hearty and/or Healthy but there is no way to tell from the rule's specification.
- Less Than. has at least two instance variables, called smaller and larger.
- Person, which works like a Prolog functor, is merely some subclass of class Object. It has at least two instance variables called name and age. Anyth ing followed by a colon is (the name of) a logic variable, so X: and Y: are both logic variable names.
- the rule states that anything that is a person, is healthy, and whose age is less than 100 is also hearty. If we have an object in the Alltalk system of class Healthy whose instance variable thing has an assigned value that is of class Person, and if th is Person object is such as to have an age th at is smaller than 100, the ALF resolution mechanism when applied against the above rule will allow us to assert that the name of our child is also the name of a hearty person.
- typing the logic variable Z allows the ALF unification rule to consider objects of subclasses of class Person (as well as objects of class Person itself) to unify with the thing object.
- object in the Alltalk system of class Healthy whose instance variable thing has an assigned value that is of class Child.
- class Child also has instance variables of name and age, inherited from class Person.
- Type qualification can be nested indefinitely. Thus we may have:
- predicates As a further integration of ALF and Smalltalk, we have established the following built-in predicates as subclasses of class Predicate: Send 0, Send 1, Send 2, ... in order to send Smalltalk messages from ALF programs. These predicates take arguments receiver, answer, selector, and n additional arguments.
- the receiver is the receiver of the message to be sent, the answer is the object returned from the message send, the selector is tiiat of the message send (i.e., a Symbol representing the selector to accomplish the message send), and the remaining arguments, if any, are arguments to the message send itself.
- the unification algorithm in these Send N predicates cause the indicated message to be sent.
- the receiver must be bound, as must the selector.
- the message is sent and the result is either bound to the answer or checked against it depending on whether the answer is free or bound in the goal being proved.
- An instance of class Alf Program has an instance variable rule Dictionary, which contains lists of the clauses (rules and facts) belonging to the program, keyed by the head predicate. As in standard Prolog, the order within the lists is the order of assertion, and the ALF resolution mechanism respects this.
- Other instance variables of Alf Program are author, date, comment, and name. Removal of a clause from a program's rule Dictionary provides a Prolog-like retract facility. Addition of a clause to a program gives a Prolog-like assert facility.
- Pgm Dictionary There is a class variable in Alf Program, called Pgm Dictionary, which registers all of the ALF programs in the system, keyed by the program's name. Queries in ALF are submitted against a specific Alf Program. Throughout execution of the query, the resolution mechanism looks first at the rule Dictionary for the program requested. If a rule with the appropriate head is not found th ere, it looks at the rules in the rule Dicaonary for the program alf Built ln. This is the way that programs can all share common rules (like the built-in predicates, and otiiers, like the ubiquitous append).
- All clauses are represented in Alltalk as instances of class Clause, and are ALF rules, facts, and queries. Included in the instance variables of class Clause are head and tail. If head is ml, we have a query. If tail is nil, we have a fact. Head must be of class Predicate, or a subclass thereof; tail is a Linked List, whose links must be of class Predicate, or a subclass thereof.
- An example of compiling a rule is given below. The compilation process merely consists of setting up the appropriate instance of class Clause, and assigning to the head and tail the appropriate objects. If the fields (instance variables) in the predicates are further specified, we set up instance objects of the appropriate class and initialize the predicates' instance variables to these objects. For any instance variable not specified (either in the predicate or elsewhere in the terms), we set up separate instances of class Logic Variable and initialize these unstated instance variables appropriately.
- the programmer can write Smalltalk methods that dynamically construct clause objects and insert them as rules in an Alf Program (or, for that matter, dynamically construct new Alf Programs). More commonly, the rules can be submitted as strings (like those above) from the program development environment, interactively, by the programmer. The strings will then be compued to the appropriate clauses and stored in the database, awaiting query submission.
- the ALF compiler is described in a subsequent section.
- Queries too can be submitted interactively as strings, compiled by the system, and the answers returned (as in standard Prolog systems). More commonly, the programmer can build up ALF queries from Smalltalk programs and submit them to existing Alf Programs without ever building a string representation of the query.
- the idea is that some objects created by an application will have instance variables that are best calculated "procedurally", via normal Smalltalk, and others that are best calculated via the logic system. The application will first calculate the values of the "procedural" instance variables, and fill in the remaining ones with appropriate instances of class Logic Variable. The constructed object can now represent a term to the logic system. Next an instance of the appropriate Predicate will be created, and the term will be assigned into an instance variable of this predicate. Now we have a query.
- the application will then submit the query to the appropriate Alf Program, and the values of the logic variables that are returned can be used to fill in the "non-procedural" instance variables of the original object replacing the previously assigned Logic Variable instances.
- the fully instantiated object can then be used in subsequent application logic.
- the ALF compiler is a combination of an ALF program and some Smalltalk programs.
- Figure 23 shows an overview of the ALF compiler, which operates as follows: a new instance of the class Alf Compiler 210 is established to compile a rule. A message is sent from an Alltalk application program 212 to the new instance 210. The parameters in the message are the rule 214 and the name 216 of the ALF program that the rule is for (the rule is in the form of a string). The compiler instance 210 will set up a new instance of an Alf Lexer 218, and pass the rule 214 to be compiled to it The instance of Alf Lexer 218 will turn the rule string into a list of tokens 220, passing this back to the Alf compiler instance, 210.
- the compiler 210 will then set up a logic query 222 using the token list and establish an Alf Query instance 224 to process it
- the Alf Query instance 224 will process the query against a specific ALF program called #alf Parser 226. If the query is solved by the alf Query 224, the alf Compiler 210 will return this indication to the original program 212, after updating the ALF program 230 with the compiled rule 228.
- the ALF program 230 is the one whose name 216 was specified by the application 212.
- the string submitted for compilation by the user is passed to an instance of class Alf Compiler via the message
- alf Compile a String for Pgm: a Pgm Name comment: a Comment which includes the string to be compiled, the name of the ALF program that is to include the string as a new clause, and a user comment to document the new clause.
- the compiler passes this string to an instance of Alf Lexer, via the message
- Alf List which returns a list of tokens, which is an instance of class Alf List.
- This Alf List instance that is returned behaves just like a Prolog list, and contains instances of class Alf Token.
- An Alf Token has, as instance variables, a type (for the parser to identify the kind of token) and a value (to be used in the code generation process).
- the compiler passes the token list as a query to an ALF program (called #alf Parser) 216, which will parse the token list and construct the clause object (as in the above example).
- the clause object is returned bound to one of the variables in the logic query.
- the logic query constructed looks like:
- the lexical analyzer 212 routines are all in class Alf Lexer.
- the primary message is
- alf Scan a String.
- a String is the string to be scanned.
- the Alf Lexer is organized as a finite state machine, and looks one character ahead to determine the next state to assume.
- the lexer removes all white space from the input string (blanks, tabs, new lines), as well as any ALF comments (which are designated by including text in single quote marks).
- the lexer assumes a new state based upon the state it is in and the look ahead character (i.e. the next character in the input string). Before switching to state 0, we will have consumed a lexeme and be ready to output a token. This logic is handled via the "accept" methods, which are:
- accept LP output token type and associated value is "().
- accept CUT output token type is #CUT and associated value is a new instance object of class Alf Cut.
- the Alf Cut objects denote a Prolog type cut and are represented by a '!' in the input string.
- accept LB output token type is "[”. This represents the start of an Alf List (which is like a Prolog list). The associated value is an Alf Empty List if the look ahead character is an "]". Otherwise, the value is a new instance of Alf List.
- accept BAR output token type and associated value is "I”.
- the "1" indicates the beginning of the tail of an Alf List, as in standard Prolog.
- output token type is #CONSTANT and associated value is an instance of eith er class Integer or Float, depending on whether the input string had no decimal specified, or had an explicit one specified.
- accept ldentifier the lexer looks the identifier up in a symbol dictionary, which is maintained by the Alf Lexer. If the identifier is in the dictionary, the associated token is used as the output If it is not in the symbol dictionary, it is added and a token is associated as follows:
- a token is set up with type #predicate Name or #class Name depending on whether the string is the name of a class that does not or does have class Predicate in the superclass chain.
- output token type is *#CONSTANT, and associated value is the instance of class Symbol that is the same as the input.
- output token type is #CONSTANT, and associated value is the instance nil, true, or else the Class object, that is represented by the input string.
- this is an ALF program and consists of clauses th at parse the Alf List passed by the Alf Lexer, and build up the objects that represent the clause.
- the objects necessary have already been constructed as the values of the various Alf Tokens in the Alf List passed by the Alf Lexer. Modification of these objects is accomplished in the parser by using the builtin predicates: Alf Send 0, Alf Send1, Alf Send2, and Alf Send3. These predicates cause message sends to occur that will modify the objects in the Alf Token values.
- the clause object that is passed back from the parser to the compiler is then sent to the Alf Program specified in the original compilation message.
- the message to update the ALF program is:
- Class Alf Program contains the necessary methods to update an Alf Program with a new clause, and to delete old clauses.
- Each Alf Program includes the following instance variables: clause Lists, which is the list of all clauses belonging to the program, and a rule Dictionary, which contains lists of clauses in the Alf Program, keyed by the class of the head atom of the rule.
- clause Lists which is the list of all clauses belonging to the program
- rule Dictionary which contains lists of clauses in the Alf Program, keyed by the class of the head atom of the rule.
- each element in this rule Dictionary is a sub-list of clauses contained with in the program, all of whose heads belong to the same class (this class being the key to the dictionary).
- rule Dictionary If no rule list is found in rule Dictionary, look in the ALF program #Alf BuiltIn for built-in rules that will unify. If found, update the link's rule Array accordingly.
- class Alf Query The main logic for solving logic queries is contained in class Alf Query.
- This class includes the following instance variables (their class is indicated inside ⁇ > : 1. query Clause ⁇ Clause> the clause to prove.
- choice Point Stack ⁇ Stack> of choice Points. This acts like a stack in that the last choice point discovered is first on the list. When this is empty, there are no more choice points that can be taken, and thus tiiere are no more answers to the query.
- Goal Stack ⁇ Goal Stack> of Goal Stack Links. This represents the current set of goals to prove. All must be solved in order to answer the query. If the Alf Query fails to prove a goal, or if the goal- Stack becomes empty, next choice point is executed in order to obtain another answer to the query.
- trail ⁇ Trail> the trail of bindings to undo at the various choice points.
- the Alf Query keeps track of the old values of logic variables in this trail stack. Undoing these unifications restores the state of query processing to a point where the next choice Point can be executed.
- the application programmer will normally set up a new Alf Query by sending the message
- the methof next Answer checks the choice Point Stack, and if th is is empty returns #fail, since there are no more answers. Otherwise, it sets up the system to process the first choice Point on the stack. To do this, it backs out all of the bindings of logic variables tiiat were made subsequent to the establishment of the choice Point These bindings are all kept on the stack called trail, and each choice Point points into this trail stack. Alf Query undoes the bindings required by processing those on the trail that follow the choice Point' s trail pointer. As in standard Prolog, these choice points represent alternative paths to take in the resolution logic for solving the query. They are placed on the choice Point Stack as they are encountered.
- a single choice Point object represents all alternatives for proving a given goal.
- Each choice Point contains a next Rule To Try which is a link in the Linked List of rules that match the first atom in the goal stack for the choice Point If this next Rule To Try is nil, Alf Query removes the choice Point and recalculates the freeze point of the current goal stack. If the next Rule To Try is not nil, Alf Query restores the goal Stack to be that which was saved in the choice Point and sends the following message to the query:
- next Choice Point is the current one on the choice Point Stack. This metiiod solve Choice continues until another answer is found, or there are no more answers for the current choice Point The method next Answer continues the processing for the next choice Point on the stack.
- the initialization logic for the query will have established the first choice Point (which is the query itself), and found the first rule To Try by looking in the rule Dictionary of the program submitted with the query.
- the method solve Choice loops for so long as it can prove atoms on the goal stack, until it cannot prove one, or the goal stack is empty.
- the latter condition constitutes successful binding of the query variables, the former results in returning #fail as no more answers exist (for the current choice Point). If a choice Point results in failure, this metiiod will not remove the choice Point from the stack, but return to method next Answer to try the next one.
- the method solve Choice initializes some temporary variables: rule To Try, atom To Prove with the first being set to a link in a list of rules that is in the next Rule To Try variable of the current choice Point, and the latter (atom To Prove) being the first goal on the current goal Stack.
- trailing trail from Query: self.
- This message is sent to the current atom To Prove.
- the unification algorithm is discussed in section 7.9 below. If the message returns #fail, indicating unsuccessful unification, the rule To Try is obtained by following the current one (remember this is a linked list of rules whose heads are of the same class as the, current atom on the goal stack). Unification is then attempted again, continuing until unification is achieved, or there are no more rules to try. The latter case causes #fail to be returned to the calling method (nextAnswer), which obtains the next choice Point and tries again.
- the method sets up another choice Point for this atom, and places it on the choice Point Stack. Backtracking will then allow the method to resume execution, trying the alternative rule.
- There are potentially other ways to prove the current atom To Prove if the rule To Try points to a non-nil next link. This means th at there are additional rules whose head could potentially unify with the atom To Prove.
- the goal that has been unified with the rule head can now be removed from the goal Stack. If the rule that the method is using has a tail, it pushes all of the atoms in the tail on the goal Stack: they represent new goals that must be proved Next, the method examines the goal Stack, and if it is empty, it returns since the query has been proven. At this point, the environment of the query wuI have all of its logic variables bound to the answer.
- Branching back to the top of the main loop will then attempt unification of the new atom To Prove with the new rule pointed to by the rule To Try, and the method continues proving goals until it fails on an atom, or runs out of them.
- Class Alf Query has debugging features that can be turned on or off (by sending messages to the query). Include are:
- Tracing There are multiple levels of tracing. It is possible to display the following:
- the basic unit of compliation in ALF is the clause.
- This class includes the instance variables head, tail, copy Env, save LV.
- the purpose of this method is to construct the copy Env for use during the resolution process.
- This environment is copied to obtain a new set of Logic Variables for every execution of the clause.
- the idea of an environment is to obtain a new set of logic variables tiiat can be pointed to by th ose in the clause itself, and which are bound and unbound during unification.
- the logic variables in the clause itself hold the index into the environment array. Thus during unification of an atom in the clause the logic variables that actually occur in the clause are not considered, but rather those that are pointed to (in the environment) by the index in the logic variables.
- Class Object contains the default unification algorithm. The algorithm checks to see if the second object (a parameter in the unification message) is of class Logic Variable, and if so, will resend the unification message to the second object, ratiier than using the default algoridim. Two objects will unify using this algorithm if they are of the same class, and each instance variable in the two objects unify. If an object has no instance variables, unification is achieved if the objects are equal.
- the default algoridim is overridden in subclasses of class Predicate, where required, in order to implement the built in predicates.
- the Alf Fail predicate always returns #fail as the answer to the unification message.
- binding this can be of any class, and is the object th at the logic variable has been bound to.
- environlndex nil means this Logic Variable is not resolved through the environment array, but points directly to its binding. not Nil means that the Logic Variable must be resolved dirough the logic variable in the environlndex, in the environment. This is tiie case when the logic variable is in a rule, and copies of the logic variables are used to do unification (one environment set up for each invocation of the rule).
- binders Env ⁇ Array> If a logic variable points to a term that itself has logic variables in it, this is used to resolve those logic variables. This is needed to trace back the variables in the original query, and when a logic variable in one rule is bound to a term that contains a logic variable from another rule. For environment logic Variables (i.e. those with environlndex not ml), it is assured that the binders Env is always nil (tiiat is the way they were set up when the clause was created).
- Z binds Y to Z which is not an environment variable (Z is a member of the environment array, and has environlndex set to nil).
- Z could itself be a term that contains environment logic variables, resolved by a different environment: the binders Env which will be found in Y.
- logic variables are dereferenced eitiier through their environlndex (first priority), or their binding. If they are bound, the environment to use for what they are bound to is found in the logic variables binders Env, the latter having meaning only for bound logic variable's, else it is nil.
- Term is a Logic Variable
- self is a local logic variable
- a Term is unbound
- the appropriate self's environment slot is set to the a Term, and success is returned.
- Term's environment slot is updated with self, and success is returned.
- the general purpose algoridim tiiat checks to see if a Term is bound to an object that is a subclass of the class of the object tiiat self is bound to or vice-versa must be invoked. If either is the case, the appropriate logic variable is placed on the trail, and it is re-bound to the binding of the other, provided all instance variables of the two bindings unify. If any instance variable fails to unify, failure is returned. Otherwise, success is returned. If both a Term and self are bound, and the objects they are bound are not type compatible in the sense above, failure is returned from the unification.
Abstract
Description
Claims
Applications Claiming Priority (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US07/261,791 US4989132A (en) | 1988-10-24 | 1988-10-24 | Object-oriented, logic, and database programming tool with garbage collection |
US261,791 | 1988-10-24 |
Publications (2)
Publication Number | Publication Date |
---|---|
WO1990004829A2 true WO1990004829A2 (en) | 1990-05-03 |
WO1990004829A3 WO1990004829A3 (en) | 1990-12-13 |
Family
ID=22994886
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
PCT/US1989/004687 WO1990004829A2 (en) | 1988-10-24 | 1989-10-23 | Object-oriented, logic, and database programming tool |
Country Status (4)
Country | Link |
---|---|
US (1) | US4989132A (en) |
EP (1) | EP0439533A1 (en) |
JP (1) | JPH04501477A (en) |
WO (1) | WO1990004829A2 (en) |
Cited By (9)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB2253500A (en) * | 1990-08-23 | 1992-09-09 | Data General Corp | Object oriented-data bases |
EP0562617A1 (en) * | 1992-03-27 | 1993-09-29 | Hitachi, Ltd. | Object management system |
WO1994014117A1 (en) * | 1992-12-17 | 1994-06-23 | Siemens Aktiengesellschaft | Process for testing at least one class of an object-oriented program on a computer |
EP0706125A1 (en) * | 1994-09-30 | 1996-04-10 | International Business Machines Corporation | Object oriented system and method for generating target language code |
EP0709773A1 (en) * | 1994-09-30 | 1996-05-01 | International Business Machines Corporation | System and method for generating target language code utilizing an object oriented code generator |
EP0945812A1 (en) * | 1998-03-23 | 1999-09-29 | Application Building Blocks Limited | Data processing systems |
EP1308845A1 (en) * | 2001-10-23 | 2003-05-07 | Sun Microsystems, Inc. | Method and apparatus for scoped memory |
CN111078548A (en) * | 2019-12-06 | 2020-04-28 | 上海励驰半导体有限公司 | Test case analysis method and device, storage medium and verification platform |
CN112463626A (en) * | 2020-12-10 | 2021-03-09 | 网易(杭州)网络有限公司 | Memory leak positioning method and device, computer equipment and storage medium |
Families Citing this family (172)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5133075A (en) * | 1988-12-19 | 1992-07-21 | Hewlett-Packard Company | Method of monitoring changes in attribute values of object in an object-oriented database |
US5265245A (en) * | 1989-04-17 | 1993-11-23 | International Business Machines Corporation | High concurrency in use manager |
US5136712A (en) * | 1989-06-29 | 1992-08-04 | Digital Equipment Corporation | Temporary object handling system and method in an object based computer operating system |
EP0414651A1 (en) * | 1989-08-14 | 1991-02-27 | International Business Machines Corporation | Prolog interrupt processing |
CA2284245C (en) * | 1989-09-01 | 2001-02-06 | Amdahl Corporation | Operating system and data base having an access structure formed by a plurality of tables |
CA2066724C (en) * | 1989-09-01 | 2000-12-05 | Helge Knudsen | Operating system and data base |
JPH0833862B2 (en) * | 1989-10-23 | 1996-03-29 | インターナシヨナル・ビジネス・マシーンズ・コーポレーシヨン | Object-oriented computer system |
US5247658A (en) * | 1989-10-31 | 1993-09-21 | Microsoft Corporation | Method and system for traversing linked list record based upon write-once predetermined bit value of secondary pointers |
US5321834A (en) * | 1989-11-28 | 1994-06-14 | Xerox Corporation | Method and system for reclaiming unreferenced computer memory space |
US5181162A (en) * | 1989-12-06 | 1993-01-19 | Eastman Kodak Company | Document management and production system |
EP0458495A3 (en) * | 1990-05-21 | 1993-04-14 | Texas Instruments Incorporated | Apparatus and method for managing versions and configurations of persistent and transient objects |
US5297279A (en) * | 1990-05-30 | 1994-03-22 | Texas Instruments Incorporated | System and method for database management supporting object-oriented programming |
AU628264B2 (en) * | 1990-08-14 | 1992-09-10 | Oracle International Corporation | Methods and apparatus for providing a client interface to an object-oriented invocation of an application |
US5291593A (en) * | 1990-10-24 | 1994-03-01 | International Business Machines Corp. | System for persistent and delayed allocation object reference in an object oriented environment |
US5758152A (en) * | 1990-12-06 | 1998-05-26 | Prime Arithmetics, Inc. | Method and apparatus for the generation and manipulation of data structures |
US5426747A (en) * | 1991-03-22 | 1995-06-20 | Object Design, Inc. | Method and apparatus for virtual memory mapping and transaction management in an object-oriented database system |
US5274803A (en) * | 1991-04-26 | 1993-12-28 | Sun Microsystems, Inc. | Method and apparatus for aligning a restored parent environment to its child environments with minimal data loss |
US5418954A (en) * | 1991-06-19 | 1995-05-23 | Cadence Design Systems, Inc. | Method for preparing and dynamically loading context files |
GB9115142D0 (en) * | 1991-07-13 | 1991-08-28 | Ibm | Data processing system |
US5392432A (en) * | 1991-08-27 | 1995-02-21 | At&T Corp. | Method for automatic system resource reclamation for object-oriented systems with real-time constraints |
US5485613A (en) * | 1991-08-27 | 1996-01-16 | At&T Corp. | Method for automatic memory reclamation for object-oriented systems with real-time constraints |
CA2077273C (en) * | 1991-12-12 | 1996-12-03 | Mike H. Conner | Language neutral objects |
US5361350A (en) * | 1991-12-12 | 1994-11-01 | International Business Machines Corporation | Object oriented method management system and software for managing class method names in a computer system |
EP0546682A3 (en) * | 1991-12-12 | 1993-12-08 | Ibm | Parent class shadowing |
US5421016A (en) * | 1991-12-12 | 1995-05-30 | International Business Machines Corporation | System and method for dynamically invoking object methods from an application designed for static method invocation |
JPH05257664A (en) * | 1991-12-12 | 1993-10-08 | Internatl Business Mach Corp <Ibm> | System and method for generating version-independent object-oriented application program |
US6256642B1 (en) * | 1992-01-29 | 2001-07-03 | Microsoft Corporation | Method and system for file system management using a flash-erasable, programmable, read-only memory |
US5860010A (en) * | 1992-03-12 | 1999-01-12 | Bull S.A. | Use of language with similar representation for programs and data in distributed data processing |
JPH0689307A (en) * | 1992-05-04 | 1994-03-29 | Internatl Business Mach Corp <Ibm> | Device and method for displaying information in database |
CA2092632C (en) * | 1992-05-26 | 2001-10-16 | Richard E. Berry | Display system with imbedded icons in a menu bar |
CA2092633C (en) * | 1992-05-26 | 2001-06-05 | Richard E. Berry | Display system with nested objects |
JPH06103075A (en) * | 1992-07-06 | 1994-04-15 | Internatl Business Mach Corp <Ibm> | Operation for object-oriented application |
US5551038A (en) * | 1992-07-16 | 1996-08-27 | International Business Machines Corporation | Directory based computer environment |
US5721900A (en) * | 1992-07-20 | 1998-02-24 | International Business Machines Corp | Method and apparatus for graphically displaying query relationships |
JP2549247B2 (en) * | 1992-07-20 | 1996-10-30 | インターナショナル・ビジネス・マシーンズ・コーポレイション | Display device and method for database |
FR2694105B1 (en) * | 1992-07-22 | 1994-11-25 | Bull Sa | Use of an on-board interpreter language for the creation of an interactive user interface definition tool. |
US5365433A (en) * | 1992-07-24 | 1994-11-15 | Steinberg Geoffrey D | System for automatically programming a functional database |
US5396630A (en) * | 1992-10-06 | 1995-03-07 | International Business Machines Corporation | Method and system for object management across process boundries in a data processing system |
US6157961A (en) * | 1992-12-21 | 2000-12-05 | Sun Microsystems, Inc. | Client-side stub interpreter |
JP2856663B2 (en) * | 1993-01-15 | 1999-02-10 | インターナショナル・ビジネス・マシーンズ・コーポレイション | Optimization method and apparatus for defining visible boundaries in compiled code |
US5497491A (en) * | 1993-01-26 | 1996-03-05 | International Business Machines Corporation | System and method for importing and exporting data between an object oriented computing environment and an external computing environment |
US6128542A (en) * | 1993-03-29 | 2000-10-03 | Cmsi Acquisition Corporation | Method and apparatus for generating a sequence of steps for use by a factory |
US5761739A (en) * | 1993-06-08 | 1998-06-02 | International Business Machines Corporation | Methods and systems for creating a storage dump within a coupling facility of a multisystem enviroment |
US5446901A (en) * | 1993-06-30 | 1995-08-29 | Digital Equipment Corporation | Fault tolerant distributed garbage collection system and method for collecting network objects |
US5379432A (en) * | 1993-07-19 | 1995-01-03 | Taligent, Inc. | Object-oriented interface for a procedural operating system |
US5396626A (en) * | 1993-08-04 | 1995-03-07 | Taligent, Inc. | Object-oriented locator system |
US5432925A (en) * | 1993-08-04 | 1995-07-11 | International Business Machines Corporation | System for providing a uniform external interface for an object oriented computing system |
JPH0756745A (en) * | 1993-08-13 | 1995-03-03 | Nec Corp | Compiler processing system for language processing program |
US5504887A (en) * | 1993-09-10 | 1996-04-02 | International Business Machines Corporation | Storage clustering and packing of objects on the basis of query workload ranking |
US5568639A (en) * | 1993-11-24 | 1996-10-22 | Menai Corporation | Method and apparatus for providing an object-oriented file structuring system on a computer |
US5463769A (en) * | 1993-12-15 | 1995-10-31 | International Business Machines Corporation | Method and apparatus using dictionary of methods and states for high performance context switching between build and run modes in a computer application builder program |
US5623657A (en) * | 1993-12-30 | 1997-04-22 | International Business Machines Corporation | System for processing application programs including a language independent context management technique |
US5522077A (en) * | 1994-05-19 | 1996-05-28 | Ontos, Inc. | Object oriented network system for allocating ranges of globally unique object identifiers from a server process to client processes which release unused identifiers |
US5680573A (en) * | 1994-07-12 | 1997-10-21 | Sybase, Inc. | Method of buffering data objects in a database |
US5812996A (en) * | 1994-07-12 | 1998-09-22 | Sybase, Inc. | Database system with methods for optimizing query performance with a buffer manager |
US5822749A (en) * | 1994-07-12 | 1998-10-13 | Sybase, Inc. | Database system with methods for improving query performance with cache optimization strategies |
US5542078A (en) * | 1994-09-29 | 1996-07-30 | Ontos, Inc. | Object oriented data store integration environment for integration of object oriented databases and non-object oriented data facilities |
US5842204A (en) * | 1994-10-07 | 1998-11-24 | Tandem Computers, Inc. | Method and apparatus for translating source code from one high-level computer language to another |
US5768564A (en) * | 1994-10-07 | 1998-06-16 | Tandem Computers Incorporated | Method and apparatus for translating source code from one high-level computer language to another |
US5737609A (en) * | 1994-10-18 | 1998-04-07 | Marcam Corporation | Method and apparatus for testing object-oriented programming constructs |
US5727203A (en) * | 1995-03-31 | 1998-03-10 | Sun Microsystems, Inc. | Methods and apparatus for managing a database in a distributed object operating environment using persistent and transient cache |
JP2924705B2 (en) * | 1995-04-10 | 1999-07-26 | 富士ゼロックス株式会社 | Memory management method and object management method |
US5867708A (en) * | 1995-11-20 | 1999-02-02 | International Business Machines Corporation | System, method, and article of manufacture for adding concurrency to a binary class in an object oriented system |
US5878428A (en) * | 1995-11-20 | 1999-03-02 | International Business Machines Corporation | System, method, and article of manufacture for adding transactional recovery to a binary class in an object oriented system |
US6405263B1 (en) * | 1995-12-04 | 2002-06-11 | International Business Machines Corporation | Method and apparatus for subclassing system object model classes in dynamic languages |
US5873092A (en) * | 1995-12-14 | 1999-02-16 | International Business Machines Corporation | Information handling system, method, and article of manufacture including persistent, distributed object name services including shared properties |
US6782538B1 (en) | 1995-12-14 | 2004-08-24 | International Business Machines Corporation | Object oriented information handling system including an extensible instance manager |
US5765153A (en) * | 1996-01-03 | 1998-06-09 | International Business Machines Corporation | Information handling system, method, and article of manufacture including object system authorization and registration |
US5809506A (en) * | 1996-01-22 | 1998-09-15 | International Business Machines Corporation | Method for creating an object base of persisent application objects in an object oriented programming environment and apparatus related thereto |
US5940616A (en) * | 1996-05-31 | 1999-08-17 | International Business Machines Corporation | Tracker class for object-oriented programming environments |
GB2318479B (en) * | 1996-10-21 | 2001-04-04 | Northern Telecom Ltd | Problem model for alarm correlation |
US6029171A (en) * | 1997-02-10 | 2000-02-22 | Actioneer, Inc. | Method and apparatus for group action processing between users of a collaboration system |
US5991765A (en) * | 1997-05-06 | 1999-11-23 | Birdstep Technology As | System and method for storing and manipulating data in an information handling system |
US5937402A (en) * | 1997-06-19 | 1999-08-10 | Ontos, Inc. | System for enabling access to a relational database from an object oriented program |
US5937410A (en) * | 1997-10-16 | 1999-08-10 | Johnson Controls Technology Company | Method of transforming graphical object diagrams to product data manager schema |
US7076784B1 (en) * | 1997-10-28 | 2006-07-11 | Microsoft Corporation | Software component execution management using context objects for tracking externally-defined intrinsic properties of executing software components within an execution environment |
US6061518A (en) * | 1997-11-25 | 2000-05-09 | International Business Machines Corporation | Data processing system and method for debugging a JavaScript program |
US6145120A (en) * | 1998-03-24 | 2000-11-07 | Lockheed Martin Corporation | Declaration programming language extension for procedural programming languages |
US6272504B1 (en) * | 1998-05-07 | 2001-08-07 | International Business Machines Corporation | Flexibly deleting objects in a resource constrained environment |
US7013305B2 (en) | 2001-10-01 | 2006-03-14 | International Business Machines Corporation | Managing the state of coupling facility structures, detecting by one or more systems coupled to the coupling facility, the suspended state of the duplexed command, detecting being independent of message exchange |
US6327587B1 (en) | 1998-10-05 | 2001-12-04 | Digital Archaeology, Inc. | Caching optimization with disk and/or memory cache management |
US6601058B2 (en) * | 1998-10-05 | 2003-07-29 | Michael Forster | Data exploration system and method |
US6327702B1 (en) * | 1998-12-30 | 2001-12-04 | Microsoft Corporation | Generating a compiled language program for an interpretive runtime environment |
US6301703B1 (en) * | 1998-12-31 | 2001-10-09 | Nortel Networks Limited | Method for transforming state-based IVR applications into executable sequences of code |
US6829770B1 (en) * | 1999-02-23 | 2004-12-07 | Microsoft Corporation | Object connectivity through loosely coupled publish and subscribe events |
US6507946B2 (en) * | 1999-06-11 | 2003-01-14 | International Business Machines Corporation | Process and system for Java virtual method invocation |
US6748555B1 (en) * | 1999-09-09 | 2004-06-08 | Microsoft Corporation | Object-based software management |
US6920636B1 (en) * | 1999-12-15 | 2005-07-19 | Microsoft Corporation | Queued component interface passing for results outflow from queued method invocations |
US6470360B1 (en) | 1999-12-20 | 2002-10-22 | Sybase, Inc. | Database system with improved methodology for page allocation |
US6934694B2 (en) * | 2001-06-21 | 2005-08-23 | Kevin Wade Jamieson | Collection content classifier |
US7689435B2 (en) * | 2001-09-11 | 2010-03-30 | International Business Machines Corporation | Method and apparatus for creating and managing complex business processes |
US20030050886A1 (en) * | 2001-09-11 | 2003-03-13 | International Business Machines Corporation | Method and apparatus for managing the versioning of business objects using a state machine |
US20030050813A1 (en) * | 2001-09-11 | 2003-03-13 | International Business Machines Corporation | Method and apparatus for automatic transitioning between states in a state machine that manages a business process |
US7627484B2 (en) * | 2001-09-11 | 2009-12-01 | International Business Machines Corporation | Method and apparatus for managing and displaying user authorizations for a business process managed using a state machine |
US20030050789A1 (en) * | 2001-09-12 | 2003-03-13 | International Business Machines Corporation | Method and apparatus for monitoring execution of a business process managed using a state machine |
US20040010780A1 (en) * | 2002-07-11 | 2004-01-15 | Nortel Networks Limited | Method and apparatus for approximate generation of source code cross-reference information |
US8108843B2 (en) | 2002-09-17 | 2012-01-31 | International Business Machines Corporation | Hybrid mechanism for more efficient emulation and method therefor |
US7415698B2 (en) * | 2002-12-09 | 2008-08-19 | International Business Machines Corporation | Testing and debugging framework for application builders |
US7519948B1 (en) | 2002-12-26 | 2009-04-14 | Judson Ames Cornish | Platform for processing semi-structured self-describing data |
US7536675B2 (en) * | 2003-02-28 | 2009-05-19 | Bea Systems, Inc. | Dynamic code generation system |
US7472400B2 (en) * | 2003-02-28 | 2008-12-30 | Bea Systems, Inc. | Method for dynamically generating a wrapper class |
US7472401B2 (en) * | 2003-02-28 | 2008-12-30 | Bea Systems, Inc. | Computer product for a dynamically generated wrapper class |
US20040172614A1 (en) * | 2003-02-28 | 2004-09-02 | Bea Systems, Inc. | Dynamic code generation method |
US7263532B2 (en) * | 2003-09-23 | 2007-08-28 | Microsoft Corporation | Region-based memory management for object-oriented programs |
US20050144615A1 (en) * | 2003-12-29 | 2005-06-30 | Shu-Chuan Chen | Modularized custom-developed software package producing method and system |
US7120776B2 (en) * | 2004-02-03 | 2006-10-10 | Oracle International Corporation | Method and apparatus for efficient runtime memory access in a database |
US8037102B2 (en) | 2004-02-09 | 2011-10-11 | Robert T. and Virginia T. Jenkins | Manipulating sets of hierarchical data |
US7454429B2 (en) * | 2004-02-14 | 2008-11-18 | Alan S Rojer | Declarative Dispatch |
US9646107B2 (en) | 2004-05-28 | 2017-05-09 | Robert T. and Virginia T. Jenkins as Trustee of the Jenkins Family Trust | Method and/or system for simplifying tree expressions such as for query reduction |
US7882147B2 (en) * | 2004-06-30 | 2011-02-01 | Robert T. and Virginia T. Jenkins | File location naming hierarchy |
US7620632B2 (en) * | 2004-06-30 | 2009-11-17 | Skyler Technology, Inc. | Method and/or system for performing tree matching |
US7712088B2 (en) * | 2004-07-08 | 2010-05-04 | Microsoft Corporation | Method and system for a batch parser |
US8881099B2 (en) * | 2004-09-10 | 2014-11-04 | Oracle International Corporation | Dynamic generation of wrapper classes to implement call-by-value semantics |
US7801923B2 (en) | 2004-10-29 | 2010-09-21 | Robert T. and Virginia T. Jenkins as Trustees of the Jenkins Family Trust | Method and/or system for tagging trees |
US7627591B2 (en) | 2004-10-29 | 2009-12-01 | Skyler Technology, Inc. | Method and/or system for manipulating tree expressions |
US7636727B2 (en) | 2004-12-06 | 2009-12-22 | Skyler Technology, Inc. | Enumeration of trees from finite number of nodes |
US7630995B2 (en) | 2004-11-30 | 2009-12-08 | Skyler Technology, Inc. | Method and/or system for transmitting and/or receiving data |
US8316059B1 (en) | 2004-12-30 | 2012-11-20 | Robert T. and Virginia T. Jenkins | Enumeration of rooted partial subtrees |
US8615530B1 (en) | 2005-01-31 | 2013-12-24 | Robert T. and Virginia T. Jenkins as Trustees for the Jenkins Family Trust | Method and/or system for tree transformation |
US20060195356A1 (en) * | 2005-02-25 | 2006-08-31 | Mark Nerenhausen | Entertainment venue data analysis system and method |
US7681177B2 (en) | 2005-02-28 | 2010-03-16 | Skyler Technology, Inc. | Method and/or system for transforming between trees and strings |
US8356040B2 (en) | 2005-03-31 | 2013-01-15 | Robert T. and Virginia T. Jenkins | Method and/or system for transforming between trees and arrays |
US7899821B1 (en) | 2005-04-29 | 2011-03-01 | Karl Schiffmann | Manipulation and/or analysis of hierarchical data |
US7580923B2 (en) * | 2005-05-10 | 2009-08-25 | Microsoft Corporation | Binding for multi-part identifiers |
US7971194B1 (en) | 2005-06-16 | 2011-06-28 | Sap Portals Israel Ltd. | Programming language techniques for client-side development and execution |
US7681178B1 (en) * | 2005-07-22 | 2010-03-16 | Adobe Systems Incorporated | Cascading style sheets (CSS) prototype pointer chaining in object-oriented environment |
US7627852B1 (en) * | 2006-01-17 | 2009-12-01 | Xilinx, Inc. | Embedding an interpreter within an application written in a different programming language |
US7958493B2 (en) | 2006-01-20 | 2011-06-07 | Kevin Edward Lindsey | Type inference system and method |
US7827537B2 (en) * | 2006-05-26 | 2010-11-02 | Oracle America, Inc | Searching computer programs that use different semantics |
US20080005727A1 (en) * | 2006-06-30 | 2008-01-03 | Robert Paul Morris | Methods, systems, and computer program products for enabling cross language access to an addressable entity |
US20080005528A1 (en) * | 2006-06-30 | 2008-01-03 | Morris Robert P | Methods, Systems, and Computer Program Products for Using a Structured Data Storage System to Provide Access to Addressable Entities in Virtual Address Space |
US20080005752A1 (en) * | 2006-06-30 | 2008-01-03 | Robert Paul Morris | Methods, systems, and computer program products for generating application processes by linking applications |
US20080005529A1 (en) * | 2006-06-30 | 2008-01-03 | Morris Robert P | Methods, Systems, and Computer Program Products for Providing Access to Addressable Entities Using a Non-Sequential Virtual Address Space |
US20080005719A1 (en) * | 2006-06-30 | 2008-01-03 | Morris Robert P | Methods, systems, and computer program products for providing a program execution environment |
US20080127220A1 (en) * | 2006-06-30 | 2008-05-29 | Robert Paul Morris | Methods, systems, and computer program products for creating an input-value-specific loadable instance of an application |
US20080005728A1 (en) * | 2006-06-30 | 2008-01-03 | Robert Paul Morris | Methods, systems, and computer program products for enabling cross language access to an addressable entity in an execution environment |
US7734890B2 (en) * | 2006-10-06 | 2010-06-08 | Okralabs Llc | Method and system for using a distributable virtual address space |
US20080120604A1 (en) * | 2006-11-20 | 2008-05-22 | Morris Robert P | Methods, Systems, And Computer Program Products For Providing Program Runtime Data Validation |
US8079023B2 (en) * | 2007-03-22 | 2011-12-13 | Microsoft Corporation | Typed intermediate language support for existing compilers |
US20080276221A1 (en) * | 2007-05-02 | 2008-11-06 | Sap Ag. | Method and apparatus for relations planning and validation |
US8332819B2 (en) * | 2007-05-03 | 2012-12-11 | Siemens Industry, Inc. | Diagnostic and trouble-shooting methods in a wireless control and sensor network |
US20080320282A1 (en) * | 2007-06-22 | 2008-12-25 | Morris Robert P | Method And Systems For Providing Transaction Support For Executable Program Components |
US8914774B1 (en) | 2007-11-15 | 2014-12-16 | Appcelerator, Inc. | System and method for tagging code to determine where the code runs |
US8954989B1 (en) | 2007-11-19 | 2015-02-10 | Appcelerator, Inc. | Flexible, event-driven JavaScript server architecture |
US8260845B1 (en) | 2007-11-21 | 2012-09-04 | Appcelerator, Inc. | System and method for auto-generating JavaScript proxies and meta-proxies |
US8719451B1 (en) | 2007-11-23 | 2014-05-06 | Appcelerator, Inc. | System and method for on-the-fly, post-processing document object model manipulation |
US8566807B1 (en) | 2007-11-23 | 2013-10-22 | Appcelerator, Inc. | System and method for accessibility of document object model and JavaScript by other platforms |
US8756579B1 (en) | 2007-12-03 | 2014-06-17 | Appcelerator, Inc. | Client-side and server-side unified validation |
US8819539B1 (en) | 2007-12-03 | 2014-08-26 | Appcelerator, Inc. | On-the-fly rewriting of uniform resource locators in a web-page |
US8806431B1 (en) | 2007-12-03 | 2014-08-12 | Appecelerator, Inc. | Aspect oriented programming |
US8938491B1 (en) | 2007-12-04 | 2015-01-20 | Appcelerator, Inc. | System and method for secure binding of client calls and server functions |
US8527860B1 (en) | 2007-12-04 | 2013-09-03 | Appcelerator, Inc. | System and method for exposing the dynamic web server-side |
US8639743B1 (en) | 2007-12-05 | 2014-01-28 | Appcelerator, Inc. | System and method for on-the-fly rewriting of JavaScript |
US8285813B1 (en) | 2007-12-05 | 2012-10-09 | Appcelerator, Inc. | System and method for emulating different user agents on a server |
US8335982B1 (en) | 2007-12-05 | 2012-12-18 | Appcelerator, Inc. | System and method for binding a document object model through JavaScript callbacks |
US8434076B2 (en) * | 2007-12-12 | 2013-04-30 | Oracle International Corporation | Efficient compilation and execution of imperative-query languages |
US8291388B2 (en) * | 2008-01-09 | 2012-10-16 | International Business Machines Corporation | System, method and program for executing a debugger |
US20090249021A1 (en) * | 2008-03-26 | 2009-10-01 | Morris Robert P | Method And Systems For Invoking An Advice Operation Associated With A Joinpoint |
US8291079B1 (en) | 2008-06-04 | 2012-10-16 | Appcelerator, Inc. | System and method for developing, deploying, managing and monitoring a web application in a single environment |
US8880678B1 (en) | 2008-06-05 | 2014-11-04 | Appcelerator, Inc. | System and method for managing and monitoring a web application using multiple cloud providers |
US7596620B1 (en) | 2008-11-04 | 2009-09-29 | Aptana, Inc. | System and method for developing, deploying, managing and monitoring a web application in a single environment |
US7653797B1 (en) * | 2008-12-31 | 2010-01-26 | International Business Machines Corporation | Optimizing a marking phase in mark-sweep garbage collectors by reducing paging activity |
JP5281452B2 (en) * | 2009-03-25 | 2013-09-04 | 株式会社日立製作所 | Memory management method, computer, and memory management program |
US20100306285A1 (en) * | 2009-05-28 | 2010-12-02 | Arcsight, Inc. | Specifying a Parser Using a Properties File |
US20110138373A1 (en) * | 2009-12-08 | 2011-06-09 | American National Laboratories, Inc. | Method and apparatus for globally optimizing instruction code |
JP5439236B2 (en) * | 2010-03-12 | 2014-03-12 | 株式会社日立製作所 | Computer system and method of executing application program |
US8997040B2 (en) * | 2010-03-24 | 2015-03-31 | Microsoft Technology Licensing, Llc | Variable closure |
US9032369B2 (en) * | 2012-03-26 | 2015-05-12 | Software Ag | Systems and/or methods for executing appropriate tests based on code modifications using live, distributed, real-time cache and feedback loop |
US9081672B1 (en) | 2013-05-30 | 2015-07-14 | Richard Michael Nemes | Methods and apparatus for information storage and retrieval using a caching technique with external-chain hashing and dynamic resource-dependent data shedding |
US10333696B2 (en) | 2015-01-12 | 2019-06-25 | X-Prime, Inc. | Systems and methods for implementing an efficient, scalable homomorphic transformation of encrypted data with minimal data expansion and improved processing efficiency |
CN112231212B (en) * | 2020-10-16 | 2023-05-09 | 湖南皖湘科技有限公司 | Method for detecting grammar error of program code |
US11907206B2 (en) | 2021-07-19 | 2024-02-20 | Charles Schwab & Co., Inc. | Memory pooling in high-performance network messaging architecture |
Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US4611272A (en) * | 1983-02-03 | 1986-09-09 | International Business Machines Corporation | Key-accessed file organization |
EP0261853A2 (en) * | 1986-09-25 | 1988-03-30 | Tektronix, Inc. | System for monitoring operation of object-oriented programs |
Family Cites Families (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US3622762A (en) * | 1969-06-11 | 1971-11-23 | Texas Instruments Inc | Circuit design by an automated data processing machine |
US4546435A (en) * | 1980-06-24 | 1985-10-08 | Herbert Frank P | Graphic computer system and keyboard |
US4570217A (en) * | 1982-03-29 | 1986-02-11 | Allen Bruce S | Man machine interface |
US4622545A (en) * | 1982-09-30 | 1986-11-11 | Apple Computer, Inc. | Method and apparatus for image compression and manipulation |
US4635208A (en) * | 1985-01-18 | 1987-01-06 | Hewlett-Packard Company | Computer-aided design of systems |
US4736320A (en) * | 1985-10-08 | 1988-04-05 | Foxboro Company | Computer language structure for process control applications, and translator therefor |
-
1988
- 1988-10-24 US US07/261,791 patent/US4989132A/en not_active Expired - Fee Related
-
1989
- 1989-10-23 JP JP1511454A patent/JPH04501477A/en active Pending
- 1989-10-23 EP EP89912328A patent/EP0439533A1/en not_active Withdrawn
- 1989-10-23 WO PCT/US1989/004687 patent/WO1990004829A2/en not_active Application Discontinuation
Patent Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US4611272A (en) * | 1983-02-03 | 1986-09-09 | International Business Machines Corporation | Key-accessed file organization |
EP0261853A2 (en) * | 1986-09-25 | 1988-03-30 | Tektronix, Inc. | System for monitoring operation of object-oriented programs |
Non-Patent Citations (14)
Title |
---|
13th Annual International Symposium on Computer Architecture, Washington D.C., US, 1986, IEEE Computer Society Press, G.S. TAYLOR et al.: "Evaluation of the SPUR Lisp Achitecture", pages 444-452 see section 3.1; figure 2 * |
1986 IEEE International Solid-State Circuits Conference, Digest of Technical Papers, 33rd ISSCC, February 1986, Lewis Winner, (Coral Gables, US), J.M. PENDELTON et al.: "A 32b Microprocessor for Smalltalk", pages 32-34 see page 32, left-hand column, lines 19-23 * |
Advances in Object-Oriented Database Systems, 2nd International Workshop, Ebernburg, DE, 27-30 September 1988 Springer-Verlag, (Berlin, DE), S. RIEGEL et al.: "Integration of Database Management with an Objectoriented Programming Language", pages 317-322 see the whole article * |
Communications of the ACM, Volume 31, No. 9, September 1988, (New York, US), R. COURTS: "Improving Locality of Reference in a Garbage-Collecting Memory Management System", pages 1128-1138 see section 4.4 * |
Communications of the Association of Computing Machinery, Volume 26, No. 6, June 1983, (New York, US), H. LIEBERMAN et al.: "A real-time Garbage Collector based on the Lifetimes of Objects", pages 419-429 see section 3 * |
Elektronik, Volume 34, No. 20, October 1985, (Munick, DE), K. BRAND et al.: "Optimierte Cross-Compiler Automatisch Erzeugt", pages 59-63 see page 59, right-hand column, line 20 - page 62, left-hand column, line 47 * |
IBM Technical Disclosure Bulletin, Volume 32, No. 5B, October 1989, (Armonk, NY, US), "Mechanism for high-speed Execution of Interpreters and high-speed Cooperative Execution with Machine Codes", pages 387-388 see page 387, lines 31-39 * |
Information Processing 86, Proceedings of the IFIP 10th World Computer Congress, Dublin, Ireland, 1-5 September 1986, Elsevier Science Publishers B.V., (Norht-Holland), (Amsterdam, NL), T. CHUSHO et al.: "A Multilingual Modular Programming System for Describing Knowledge Information Processing Systems", pages 903-908 see section 2.2 * |
Review of the Electrical Communication Laboratories", Volume 29, Nos. 1-2, January/February 1981, (Tokyo, JP), M. HASHIMOTO et al.: "Time Sharing System Oriented Database Management System", pages 16-31 see section 4.1, figure 2 * |
Sigplan Notices, Volume 19, No. 5, May 1984, ACM, (Pittsburgh, US), D. UNGAR: "Generation Scavenging: Storage Reclamation Algorithm", pages 157-167 see section 8.1 * |
Sigplan Notices, Volume 22, No. 12, 1987, P.D. O'BRIEN et al.: "The Trellis Programming Environment", pages 91-102 see section 6 * |
Sigplan Notices, Volume 23, No. 10, October 1988, ACM, (US), F. MELLENDER: "An Integration of Logic and Object-Oriented Programming" pages 181-185 see the whole article * |
Software Practise & Experience, Volume 19, No. 8, August 1989, John Wiley & Sons, Ltd, (Chichester, Sussex, GB), A. STRAW et al.: "Object Management in a Persistent Smalltak System", pages 719-737 see the whole article * |
The 11th Annual International Symposium on Computer Architecture, Ann Arbor, Michigan, 5-7 June 1984, IEEE, (US), D. UNGAR et al.: "Architecture of SOAR: Smalltalk on a RISC", page 188-197 see section 3 * |
Cited By (15)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB2253500A (en) * | 1990-08-23 | 1992-09-09 | Data General Corp | Object oriented-data bases |
US5526519A (en) * | 1992-03-27 | 1996-06-11 | Hitachi, Ltd. | Memory management technique for efficient execution of procedures in objects |
EP0562617A1 (en) * | 1992-03-27 | 1993-09-29 | Hitachi, Ltd. | Object management system |
WO1994014117A1 (en) * | 1992-12-17 | 1994-06-23 | Siemens Aktiengesellschaft | Process for testing at least one class of an object-oriented program on a computer |
US5794043A (en) * | 1992-12-17 | 1998-08-11 | Siemens Aktiengesellschaft | Method for testing at least one class of an object-oriented program on a computer |
EP0706125A1 (en) * | 1994-09-30 | 1996-04-10 | International Business Machines Corporation | Object oriented system and method for generating target language code |
EP0709773A1 (en) * | 1994-09-30 | 1996-05-01 | International Business Machines Corporation | System and method for generating target language code utilizing an object oriented code generator |
US5875331A (en) * | 1994-09-30 | 1999-02-23 | International Business Machines Corp. | System and method for generating target language code utilizing an object oriented code generator |
EP0945812A1 (en) * | 1998-03-23 | 1999-09-29 | Application Building Blocks Limited | Data processing systems |
AU746062B2 (en) * | 1998-03-23 | 2002-04-11 | Application Building Blocks Limited | Data processing systems |
EP1308845A1 (en) * | 2001-10-23 | 2003-05-07 | Sun Microsystems, Inc. | Method and apparatus for scoped memory |
CN111078548A (en) * | 2019-12-06 | 2020-04-28 | 上海励驰半导体有限公司 | Test case analysis method and device, storage medium and verification platform |
CN111078548B (en) * | 2019-12-06 | 2023-05-23 | 上海励驰半导体有限公司 | Test case analysis method and device, storage medium and verification platform |
CN112463626A (en) * | 2020-12-10 | 2021-03-09 | 网易(杭州)网络有限公司 | Memory leak positioning method and device, computer equipment and storage medium |
CN112463626B (en) * | 2020-12-10 | 2023-07-11 | 网易(杭州)网络有限公司 | Memory leakage positioning method and device, computer equipment and storage medium |
Also Published As
Publication number | Publication date |
---|---|
EP0439533A1 (en) | 1991-08-07 |
WO1990004829A3 (en) | 1990-12-13 |
JPH04501477A (en) | 1992-03-12 |
US4989132A (en) | 1991-01-29 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US4989132A (en) | Object-oriented, logic, and database programming tool with garbage collection | |
Appel et al. | A standard ML compiler | |
Somogyi et al. | The execution algorithm of Mercury, an efficient purely declarative logic programming language | |
Kelsey et al. | A tractable Scheme implementation | |
Chambers et al. | An efficient implementation of SELF a dynamically-typed object-oriented language based on prototypes | |
US6199095B1 (en) | System and method for achieving object method transparency in a multi-code execution environment | |
US6226789B1 (en) | Method and apparatus for data flow analysis | |
US7007005B2 (en) | Method and structure for reducing search times | |
US6535903B2 (en) | Method and apparatus for maintaining translated routine stack in a binary translation environment | |
US7036118B1 (en) | System for executing computer programs on a limited-memory computing machine | |
Houri et al. | A sequential abstract machine for Flat Concurrent Prolog | |
Wirfs-Brock et al. | A overview of modular smalltalk | |
Carlsson et al. | Message analysis for concurrent programs using message passing | |
Marlow et al. | The new GHC/Hugs runtime system | |
Jones et al. | The STG runtime system (revised) | |
Carlsson | The SICStus Emulator | |
Bogle | A Safe, Efficient Object Database Interface Using Batched Futures | |
Jacobs et al. | UCL+ P—defining and implementing persistent Common Lisp | |
Printezis et al. | Defining and handling transient fields in PJama | |
Bowen et al. | Northeast Artificial Intelligence Consortium Annual Report 1986. Volume 6. Part B. Knowledge Base Maintenance Using Logic Programming Methodologies | |
Haeberlen | Using platform-specific optimizations in stub-code generation | |
Johannes_Kepler_Universität | Metaprogramming in Oberon | |
Phan et al. | Region-based memory management for Mercury programs | |
Dietrich | Adapting a portable SIMULA compiler to Perkin-Elmer computers in a UNIX environment | |
Bottema | Asynchronous Message Passing and Concurrent Scheme Implementation |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
AK | Designated states |
Kind code of ref document: A2 Designated state(s): JP |
|
AL | Designated countries for regional patents |
Kind code of ref document: A2 Designated state(s): AT BE CH DE FR GB IT LU NL SE |
|
AK | Designated states |
Kind code of ref document: A3 Designated state(s): JP |
|
AL | Designated countries for regional patents |
Kind code of ref document: A3 Designated state(s): AT BE CH DE FR GB IT LU NL SE |
|
WWE | Wipo information: entry into national phase |
Ref document number: 1989912328 Country of ref document: EP |
|
WWP | Wipo information: published in national office |
Ref document number: 1989912328 Country of ref document: EP |
|
WWW | Wipo information: withdrawn in national office |
Ref document number: 1989912328 Country of ref document: EP |