System and method for non-sequential program statement execution with incomplete runtime information6028999Abstract A system and method for non-sequential program execution in an incompletely assembled runtime environment. In a program debugging context, a primary advantage is that neither a fully linked executable nor a complete code base is required to execute the program. As well, it is not necessary to begin execution at the traditional program entry point. Six key methods are described. Virtual execution initialization logic involves establishing the runtime environment within the context of the first statement of execution. Statement execution logic concerns execution of a program statement and a technique by which the runtime copes with incomplete information. Reset execution point logic allows the user to randomly reposition the current execution point within a program without violating the runtime environment. Finally, methods for adding and deleting callers into/from the runtime stack are outlined. Extensions for multi-process and thread support are outlined as well as the incorporation of standard and application libraries into the execution model. Claims I claim: Description I. FIELD OF INVENTION
______________________________________
Procedure: Read Code Item into Global Dictionary
Input: Identity of code item to parse
Begin.sub.-- Procedure:
While parsing code item
On case "statement type"
case "Variable Type Information":
If type is not in global dictionary
Create a dictionary item
Add dictionary item to global dictionary
End.sub.-- If
continue
case "Variable Instance Information":
If instance is not in the global data list
Create a global data item
Assign the data item's name
Assign a unique identifier
Assign the appropriate dictionary item describing its type
Add global variable item to global variable list
End.sub.-- If
continue
case "Routine Statement":
If routine is not in global routine list
Create global routine item
Assign the routine's name
Assign a unique identifier
Assign the routine's location within code item
Add global routine item to global routine list
End.sub.-- If
continue
case "Included code item":
Call "read code item into global dictionary" on referenced
code item /*recursive*/
continue
Default:
continue
End.sub.-- On.sub.-- Case
End.sub.-- While
End.sub.-- Procedure
______________________________________
Data Maintained by the Local Data Dictionary By way of overview, the local data dictionary 14 preferably maintains detailed information about individual application routines. This includes the location of individual executable program statements, local variables, and the context structure of the routine. The location information allows the interpreter 11 to acquire quick access to executable statements. Local variable information and a nested context structure information allows the virtual runtime an easy way to set up its stack when any statement in a routine is to be executed. FIG. 4 shows an example of the information maintained by the local data dictionary 14. The local routine list 28 points to a list of local routine entries 29, each of which contains program information about the respective routine. A routine entry has a routine name 30, a unique routine identifier 31 assigned by the local data dictionary, a pointer to the statement map 22, and a pointer to the context tree 23. The statement map 34 consists of a table of information relating each statement 35 in the routine to its location 36 in the program content and it associated context reference 37. A statement's location 36 is identified during parsing and is related to where the program statement is stored in the program content. For example, for a program residing within a file system, a statement location within that program would indicate the file name, line number, and column number where the program text for that statement starts. The context reference 37 is discussed below. A context 39 represents a nested set of executable statements within a routine. Any given routine is structured into a single-rooted tree of contexts. Each context maintains a set of variables local to it, and all variables within a context are programmatically visible to it and to all contexts nested underneath it. In other words, these are the local variables defined within that context. Returning to FIG. 4, Routine.sub.-- Context 33 points to a tree of context structures 38. Each member of the context tree 38 is called a context 39. Each context 39 has a unique context identifier 40 assigned by the local data dictionary. It also has an array 41 of data items 42 which hold information about the local variables within that context 39. The context also has a pointer 43 to a set of local dictionary items 44 representing data types defined within this context. Much like the global dictionary item 22, the local dictionary item 44 describes a data type and the data layout of that type, and is again typical of information maintained by data dictionaries in compiler technology, and thus is not discussed in further detail herein. The context reference 37 is a reference to one of the contexts 39 in the context tree 38. Each data item 42 within a context has a data name 45 holding the name of the local variable, a unique identifier 46 assigned by the local data dictionary, and a pointer to a dictionary item describing the type of the variable. This pointer may refer to a dictionary item from the global dictionary or from some context's local dictionary. Furthermore, we may assume for convenience that the root context in the context tree contains information relevant to the input and output parameters of the routine within its Data.sub.-- Item array. As a policy, the local dictionary 14 may maintain information about any routine as long as that routine is involved in the execution, i.e. is referenced on the runtime stack. This is due to the likelihood of its being referenced again as the stack is unwound. If the virtual runtime has no logical need for information about a particular routine within the local dictionary, that information may be discarded from the local dictionary and re-constructed as needed later. While not entirely essential to design, this policy represents a trade-off of memory usage versus processing time within the virtual program emulator 9, and as an optimization issue is not discussed further here. A procedure for parsing a routine into the local data dictionary 14 will now be described. This is a utility routine for the main actions to be described later with reference to FIG. 7. This routine is used to parse a program routine. It picks out and identifies all executable statements 35, their locations 36, and their associated program context 37, and puts that information into the statement map 34. It constructs the program contexts 39 and builds the context tree 38. For each context, it builds its associated dictionary items 44 describing new program semantic types. It also builds data items 42 defining local variable instances within the context 39. All this information comprises the local data dictionary 14. It is assumed that parsing occurs on some code item containing that routine.
______________________________________
Procedure: Parse Routine into Local Dictionary
Input: Code item for routine and location of routine within code item
Begin.sub.-- Procedure
Position interpreter to read at location of routine within code item
Read routine declaration
Create local routine entry
Assign Routine.sub.-- Name from parsed declaration
Find associated global routine item in global dictionary
Assign Routine.sub.-- Id from global routine item
Add local routine entry to local routine list
Build root context
Assign unique context identifier
Install parameters as local variables
Assign context as current context
Assign context to Routine.sub.-- Context
while parsing routine
On case "statement type"
case "New Context":
Build context and insert into context tree
Assign unique context identifier
Assign as current context
continue
case "Executable Statement":
Add statement information to statement map
specifying the statement identifier or number, and location
Assign context identifier from current context
continue
case "New Type":
Build Dictionary.sub.-- Item
Insert Dictionary.sub.-- Item into local.sub.-- Dictionary in current
context
continue
case "Local Variable":
Build Data.sub.-- Item
Assign the variable's name to Data.sub.-- Name
Assign a unique identifier to Data.sub.-- Id
Assign a reference to the appropriate dictionary item for the
instance's type to Dict.sub.-- Item
Add Data.sub.-- Item to Local.sub.-- Data.sub.-- Item in current
context
continue
Default:
continue
End.sub.-- On.sub.-- Case
End.sub.-- While
End.sub.-- Procedure
______________________________________
Data Maintained by the Virtual Runtime Emulator By way of overview, the virtual runtime emulator 15, preferably maintains information about the execution state of an application program. This includes memory management, local and global variable management, and program stack maintenance. According to the present invention, the virtual runtime emulator does not require execution to begin at application entry, and also does not require as much information to exist within it. It only needs what is essential to execute the current statement and in that sense it is incompletely assembled. FIGS. 5 and 6 illustrate examples of the information maintained by the virtual runtime emulator 15. FIG. 5 depicts virtual memory management and global variable management. FIG. 6 depicts stack maintenance which includes the maintenance of local variable instances. As an error detection tool, virtual debugging concerns the use or abuse of application memory, allocated or otherwise. Therefore the virtual runtime 15 contains a memory management system that provides enough structure to detect memory protection violations or over-writes. This is achieved by monitoring or tracking all utilized memory. For any memory utilized by the program, a corresponding memory buffer is allocated within the virtual runtime. A virtual address is also assigned for the application program to reference it. This is done to simulate the sequential placement of memory in a real machine making it more realistic for detecting errors such as over-writing the program stack. The combination of real buffer and virtual address is recorded and monitored by the virtual runtime. FIG. 5 depicts examples structures used for virtual memory management and global variable management in accordance with the present invention. As depicted, the allocation list 48 includes a list of allocated items 49. Each allocation item 49 has a real address which points to a real allocated buffer 51 for the application to use. This memory is assigned a virtual address 52 which is used by the application to reference the buffer 51. The allocated item 49 also records the length 53, as well as the routine identifier 54 of the routine that allocated or owns that memory, and the statement identifier within the routine 55 that allocated that memory. This information is useful, for example, to pinpoint the location of errors detected during execution. The global variable list 56 tracks all global variable instances utilized during execution. This usually comprises a subset of all global variable instances in the program, since virtual debugging does not require all this information at once. This data set is only as large as necessary for execution to proceed, and grows to accommodate further execution. This list consists of a set of global valuable items 57. Each global variable item contains a data identifier 58 which matches to a global data item found in the global data list 23. It also points to an allocated item 59 which holds the associated data value. The init.sub.-- map field 60 is a structure for determining which fields are initialized, that is, have or have not been set by the application program. The init.sub.-- map structure is much like the dictionary item structure referred to by the data.sub.-- id 46, except that each field has a value indicating whether the field has been set by the application (True) or not (False). The structure of this artifact is much like that found in data dictionaries in compiler technology and will not be discussed further. FIG. 6 illustrates an example of a structure of the runtime stack in the virtual runtime emulator 15 in accordance with the present invention. The stack list 61 consists of an ordered set of stack entries 62. The order of the list reflects the called-by order that could have occurred during execution with the top stack entry corresponding to the current routine being executed. Note that in virtual debugging it is not necessary for the bottom stack entry to correspond to the real entry point of the application program. The bottom entry only reflects where execution in debugging began. It is required however, that between the bottom and top entries, the stack is consistent as a logical calling sequence within the application program. Each stack entry contains the global identifier of the routine 63 as maintained by the global data dictionary. It also contains the global identifier of the calling routine 64 and the statement identifier or number 65 within that routine from which the call was made. It also contains a pointer 66 to the list of nested execution contexts 67 which encapsulate the state of execution within that routine. This context list is an ordered list of execution stack contexts 68. Execution stack contexts are executing versions of contexts 39 as defined in the local data dictionary. The top entry corresponds to the execution context that is holding the current statement of execution, while the bottom entry is the execution context at entry into the routine. Each stack context has a context identifier 69 corresponding to the context identifier 40 of the defining context 39 from the local data dictionary. It also contains a field 70 to hold the execution state of the interpreter when the executing statement issues a call (details of this will be discussed later) that results in a successive stack entry. It also contains a pointer 71 to a local variable table 72. The local variable table contains details about each local variable instance within a given execution context, each row of the table corresponds to a local variable instance. Each row of the local variable table has a field Data.sub.-- Id 73 corresponding to the same Data.sub.-- Id 46 defining that local variable in the local dictionary. Another field holds an allocated item 74 containing the value of that local variable instance. The Init.sub.-- Map field 75 is used for determining which fields within the instance have been set by the application program or not, and is identical to that discussed for global variable items 60. An exemplary procedure for building a virtual stack entry 62 will now be described. This is a utility routine for the main actions to be described with reference to FIG. 7. This routine creates and initializes a stack entry 62 for the stack list 61 in the virtual runtime. It initializes the entry's context list 67 and initializes the local variable tables 72.
______________________________________
Procedure: Building a Virtual Stack Entry
Input: Identity of routine being entered and statement identifier,
and caller (routine identifier and statement identifier)
Begin.sub.-- Procedure
Create stack entry
Find associated global routine entry in global data dictionary
Assign Routine.sub.-- Id from global routine entry
Assign identifier of calling routine and statement identifier
where call made
Locate branch of context tree in local data dictionary for
routine from root to context holding routine statement
Assign the state of the interpreter to Suspended.sub.-- Interp
For each context in branch starting at root
Create a stack context and add last to context list
Assign context id from context in local data dictionary
For each local variable in context
Add a row to local variable table
Assign the data identifier found in local data dictionary
to Data.sub.-- Id
Construct an appropriate allocated item and assign to
Alloc.sub.-- Item
Construct and set an appropriate initialization map and
assign to Init.sub.-- Map
End.sub.-- For
End.sub.-- For
End.sub.-- Procedure
______________________________________
Detailed Description of Methods of Execution FIG. 7 depicts an example of the virtual execution services 10 logic. As depicted, the methods of execution include logic for system initialization 76, virtual execution initialization 78, statement execution 79, resetting execution point 80, insert caller into stack 81, and deleting caller from stack 82. These will be described later in detail. Recall also the three low-level utility procedures described earlier that read a code item into the global data dictionary 13, read a routine into the local data dictionary 14, and build a stack entry 62. The logic that dictates these actions is found in the virtual execution services 10 component in the virtual program emulator 9. Referring again to FIG. 7, after system initialization 76, a decision is made which action 77 should be taken (based on user input or other criteria). The actions are virtual execution initialization 78, statement execution 79, reset execution point 80, insert caller into stack 81, and delete caller from stack 82. After that, logic returns to the action decision point 77 for iteration. The following pseudo-code describes an example of the system initialization 76 logic having features of the present invention. Note that there is no need to set up runtime global instances until needed or requested. This routine initializes the virtual program emulator 9. It reads in a user specified list of code items, and parses these into the global data dictionary 13.
__________________________________________________________________________
Procedure: System Initialization
Input: A set of user-specified code items for pre-analyzed into the
system, allowing easy
reference to existing routines.
Begin.sub.-- Procedure
for each code item in user specified list
Read code item into global dictionary
/* utility procedure */
End.sub.-- For
End.sub.-- Procedure
The following pseudo-code describes an example of the virtual execution
initialization 78 logic
having features of the present invention. This routine may be called at
the first virtual statement
execution. It initializes the virtual stack list 61 with an initial stack
entry 62 using information
from the specification of the initial program statement to execute. It is
assumed that the stack list
61 is empty.
Procedure: Virtual Execution Initialization
Begin.sub.-- Procedure
Build a virtual stack entry based on routine and statement number /*
utility procedure */
Position interpreter to beginning of statement
Insert stack entry into Stack.sub.-- List in virtual runtime /* FIG. 7a
and procedure */
End.sub.-- Procedure
__________________________________________________________________________
The following pseudo-code describes an example of the virtual statement execution 79 logic having features of the present invention. This routine may be used to execute a routine's statement. It reads and updates information about the global variables in the global variable list 56, and local variables in contexts 39 found in local routine entries 29. It executes operations on data as defined by the statement semantics. On missing or erroneous information, it informs or asks the user for further information.
__________________________________________________________________________
Procedure: Virtual Statement Execution
Input/Assumption: Interpreter is positioned at executable statement
Begin.sub.-- Procedure
Reset interpreter state for executing new statement
If context has changed
Delete stack contexts to first context that is to remain
Add new contexts until context is found that contains statement
(refer to Building virtual stack item for related logic)
End.sub.-- If
While computing on execution tree
On case tree-node type
Case "Operation":
Perform operation
If error
Report error and ask user for information
If new data values specified and set
return to top of while-loop to repeat execution of this
operation
End.sub.-- If
End.sub.-- If
If assignment to a variable instance
ensure that Init.sub.-- Map has corresponding variable is set to True
End.sub.-- If
continue
Case "Read Value of Data Instance":
If global data and not in virtual runtime
Build global variable item
Locate global data dictionary item for type of data, assign to
Data.sub.-- Id
Build appropriate allocated item and assign to Alloc.sub.-- item
Build appropriate initialization map and assign to Init.sub.-- Map
Add global variable item to global variable list
End.sub.-- If
Retrieve value for this data
if value has unknown state
Ask the user for value
continue
Case "Reference Data Instance":
If global data and not in virtual runtime
Build global variable item
Locate global data dictionary item for type of data, assign to
Data.sub.-- Id
Build appropriate allocated item and assign to Alloc.sub.-- item
Build appropriate initialization map and assign to Init.sub.-- Map
Add global variable item to global variable list
End.sub.-- If
Retrieve pointer value information
continue
Case "Call":
If called routine not in global dictionary
Ask user for code item of routine
if none
Ask user to provide results of call
else
Parse code item into global dictionary
Endif
If called routine not in local dictionary
Parse routine into local dictionary
Build virtual stack entry for calling routine
continue
case "Return":
Remove top stack entry from stack list in virtual runtime
Reset interpreter state to that found in Suspended.sub.-- Interp on stack
entry
Delete stack entry and all related information
End.sub.-- On.sub.-- Case
End.sub.-- While
End.sub.-- Procedure
__________________________________________________________________________
The following pseudo-code describes an example of the reset execution point 80 logic having features of the present invention. This routine may be used to forcibly reset the virtual execution point. It is assumed that a point of execution already exists, and a new statement number has been specified within the current routine as the next executable statement.
______________________________________
Procedure: Reset Execution Point
Begin.sub.-- Procedure
On case context change type
case "new context==old context":
Set interpreter to new statement
continue
case "new context precedes old context":
for each stack context above the new one
remove stack context from context list
delete stack context and related information
End.sub.-- For
Set interpreter to new statement
continue
case "new context succeeds old context":
Locate new contexts in local dictionary
Build new stack contexts to match each new context
Insert context into context list appropriately
Set interpreter to new statement
continue
case "new context is a sibling context":
Determine highest context common to current execution and
new context list
Delete all stack contexts above the common context and the top
Add all new contexts appropriately
continue
End.sub.-- On.sub.-- Case
End.sub.-- Procedure
______________________________________
FIG. 7a depicts an example of the insert caller into stack 81 logic in accordance with the present invention. The stack list 61 is initially comprised of two stack entries A 700 and C 701, with A calling C. The stack entry B 702 is to be inserted as a caller between A and B producing entry 703. First, a check 704 is made to determine if the insertion is legal. It must be determined that A 700 already calls the routine represented by B 702 at A's current statement, and that B 702 at its current statement calls C 701. If that is the case, the stack entry 702 is inserted 705 into the stack list. Next the Calling.sub.-- Rtn.sub.-- Id 706 and Calling.sub.-- Rtn.sub.-- Stmt 707 of B 702 must be updated 708 to reference A 700. Similarly the Calling.sub.-- Rtn.sub.-- Stmt 709 of C 701 must be updated 710 to reference B 702. Next the context 711 of C 701 is found that contains the routine's parameters. These are checked for parameters passed by reference which are then updated 712 appropriately to values from B 702. The following pseudo-code describes another example of the insert caller into stack 81 logic having the features of the present invention. This routine is used to insert a caller anywhere in the stack, obeying consistency of calling within the stack. It is assumed that a calling routine and statement number has been specified along with the position within the virtual call stack to be inserted.
______________________________________
Procedure: Insert Caller into Stack
Input Identity of routine to be inserted into to stack
Indication of where in stack to insert entry
Begin.sub.-- Procedure
if calling routine not in local dictionary
Parser routine into local dictionary
Build stack entry
if stack predecessor exists and is not calling this routine or
stack successor exists and is not called by the statement specified
in new calling routine
report error to user
exit
End.sub.-- If
Insert stack entry into stack
If predecessor in stack exists
Set Calling.sub.-- Rtn.sub.-- Id and Calling.sub.-- Rtn.sub.-- Stmt in
new stack entry to
reference predecessor
If successor in stack exists
Set Calling.sub.-- Rtn.sub.-- Stmt in successor entry to reference new
stack
entry
End.sub.-- If
For the successor, adjust any input parameters passed by reference to
reflect variables in the new stack entry
End.sub.-- Procedure
______________________________________
FIG. 7b depicts an example of the delete caller from stack 82 logic in accordance with the present invention. The stack list contains three stack entries A 750 calling B 751 calling C 752. It is intended to remove B 751 from the stack list. First a check 753 is made to ensure that the removal is allowed. That check consists of ensuing that A 750 at its current statement references C 752. If that is true, the entry may be removed and deleted 754. Next the Calling.sub.-- Rtn.sub.-- Id 755 and Calling.sub.-- Rtn.sub.-- Stmt 756 of C 752 are updated 757 to reference A 750. After that the context 758 of C 752 holding the routine's parameters is found and it is checked for variables passed by reference. Those are changed 759 to reference corresponding values form A 750. The following pseudo-code describes another example of the delete caller from stack 82 logic having features of the present invention. This routine is used to delete any entry from the stack, obeying consistency of calling within the stack.
______________________________________
Procedure: Delete Caller from Stack
Input: Stack entry representing caller to be deleted from stack
Begin.sub.-- Procedure
Locate respective Stack Entry
If stack entry has predecessor and it is not calling the same routine
specified by the successor (if it exists) of the target stack entry
report error to user
exit
End.sub.-- If
Remove respective Stack Entry and delete it
If the stack entry had a successor,
Update the successor's Calling.sub.-- Rtn.sub.-- Stmt to refer to the
deleted
entry's predecessor
If stack entry had a successor, adjust any input parameters passed by
reference to reflect variables in the predecessor
End.sub.-- Procedure
______________________________________
Alternative Embodiments Multi-Process/Multi.sub.-- Thread Multi-process and multi-thread support is achieved through a simple extension to the present invention. One extends the runtime to include the conventional notion of processes and threads, with each process having a set of threads. Each process has its own global 13 and local data dictionary 14, and its own virtual runtime memory and global variable management, and their dependent sub-structures. Each thread is assigned a stack list 16 and its dependent sub-structures. At the virtual execution services 10 level, one must extend primitive actions by specifying to which process and thread the action applies. This extension also impacts error detection. The process and thread producing a violation should be identified on the error. For example, if execution on one thread over-writes memory that is associated with another thread (such as its stack), the victim process and thread should also be identified when the violating process and thread are reported as producing the error. Test Data Composition In order to enhance software testing utilizing virtual debugging, it is desirable to have a tool which could manufacture data structure instances of arbitrary complexity in an interactive fashion. These instances may be any composition of global data, local data, data structure instances, and data arrays. Since the specification of this information is complex, this tool would ideally have a graphical user interface to facilitate the contriving of complex data structure instances and relationships. It would also be capable of saving and retrieving this information from storage media. Finally, the virtual debugger should be able to retrieve these instances either directly from the tool as it is active, or from the saved information on storage media. The technical details of this tool's construction and user interface, are fairly straight forward to one of skill in the art, and will not be discussed further herein. The interaction of this tool with the virtual program emulator however is a significant notion, which is now described with reference to FIG. 8. While such a tool would be optimal and effective within a working environment, outside of its availability, other conventional tools could serve the same function, albeit less effectively. For example, one could use a standard text editor to define data structure instances and store them on standard storage media. The standard cut and paste operations could serve as the transport medium between the editor and the virtual program emulator 84. The virtual program emulator could as well read that data from storage media. In this scenario, referring to FIG. 8, the text editor would replace the data scenario editor 85. (Note: the representation of the virtual program emulator in FIG. 8 is somewhat different than that in FIG. 2. Here, the global and local dictionaries are combined. This is not to represent a different architecture, but only to simplify the discussion. The virtual program emulators of both FIGS. 2 and 8 represent the identical logical component.) As depicted in FIG. 8, the virtual program emulator 84 interacts with the proposed tool, called the data scenario editor 85. The data scenario editor is shown having a graphical user interface 86, and an interaction 87 with a data repository 88. The data structure instances 861 depicted on the user interface 86 are conventionally stored to and retrieved from the data repository 88. The two aspects that are not unique in themselves are now presented for completion. These tools may interact through any number of transport protocols 89 such as TCP/IP, local pipes, or through established middle wares or component technologies. The virtual execution services component 90 of the virtual program emulator 84 arbitrates communication for the virtual debugger. However, this decision simplifies the presentation. The data scenario editor 85 interacts with the global and local dictionaries 91 by way of the data path 92 to the virtual execution services 90. This information is used to facilitate the manufacture of data structure instances. That is, the data scenario editor uses these definitions to provide data structure layouts to the granularity of individual single-valued fields for which the tool's user may specify values including reference values to other data structure instances. The virtual program emulator 84 may request data structure instances from the data scenario editor at various times, such as when the virtual interpreter requests data for uninitialized references. In that transaction, data structure instance information is transferred from the data scenario editor to the virtual runtime emulator 93 by way of the data path 94 from the virtual execution services 90. In the virtual program emulator the instances are installed in the virtual runtime appropriately, by allocating sufficient virtual memory and copying explicit data into those areas. In the absence of a data scenario editor tool, the virtual program emulator may retrieve pre-built data instances directly 95 from storage media 88. In this case all of the above activities occur as before with the virtual execution services reading data instance data directly from storage media. Incorporation of Application Libraries Thus far, virtual debugging has been presented for programs at a pure language level. That is, all application program functionality derives from language statement execution. As presented here, when a program is called that is inaccessible to the virtual program emulator, the user is asked to supply the source code for that program. There are many cases where these programs are pre-built and reside in libraries outside the domain of the current application, such as standard runtime libraries, or ancillary program libraries from other applications. Typically, the program source for these libraries is not available. Three solutions to this problem are presented here, all having various tradeoffs (depicted in FIGS. 9, 10, and 11). (Note: the representations of the virtual program emulator in FIGS. 9, 10 and 11 are somewhat different than that in FIG. 2. Here, the global and local dictionaries are combined. Those skilled in the art will appreciate that is not to represent a different architecture, but only to simplify the discussion. The virtual program emulators of these figures represent identical logical components.) FIG. 9 depicts an example of a block diagram for the integration of application libraries into the virtual program emulator 96 using the library source 97, also called the source scenario. As depicted, the virtual program emulator 96 has access via data path 98 to the program content (source) for the library 97. In the source scenario, the application library source 97 is described to the virtual program emulator as program content holding the source of that library. Just as any program content is read and analyzed by the virtual program emulator, this source is similarly processed via the data path 98 to the global/local dictionary 99. Here, the virtual program emulator 96 functions as before, i.e., interacting with the specified program content appropriately on each call to routines within the library 97 by the virtual interpreter 100. At the expense of having the library source available, this approach adds no burden of additional function to the present invention as already defined. FIG. 10 depicts an example of a block diagram for the integration of application libraries into the virtual program emulator using bytecode versions of library source, also called the bytecode scenario. Here, it is assumed that the library source 97 has been translated into a bytecode representation, which the virtual interpreter 106 is capable of executing. As depicted, the virtual program emulator 101 has access to via a data path 107 to an application library 102. The application library 102, which in this instance consists of a set of routines 103, each compiled into an interpretive bytecode. The global/local dictionary 104 reads the application library 102 via a data path 105 to determine the identity of the library's routines and thereby distinguish these routines from others. It is also assumed that the global dictionary is capable of determining all the global data instances defined within the library, i.e., the information encoded into the application library through a variant of the bytecode representation. This also applies to local dictionary information describing contexts and local variables, for example. When the interpreter 106 calls a routine 103 within the library, the interpreter reads the corresponding bytecode and executes accordingly. It is assumed that references to variables and virtual emulated memory, as well as operations specified by the bytecode are understood by the virtual program emulator. That is a detail beyond the scope of this discussion. In the bytecode scenario, one gains speed of execution at the expense of requiring a re-compilation phase for the library source. One also gains the ability to distribute program libraries without distributing the source programs for it. On the other hand, this approach requires a new type of compiler to be designed for this re-compilation, as well as moderate changes to the architecture of the virtual program emulator to accommodate the bytecode interpretation. FIG. 11 depicts an example of a block diagram for the integration of application libraries into the virtual program emulator using a library's binary, also called the binary scenario. In this scenario, the library 109 is utilized by the virtual program emulator 108 in a binary distributed format. For example the application library 109 could be compiled into a standard machine code representation through standard compilation techniques. It is assumed that the library 109 in this format is callable from the virtual program emulator 108. As in the other scenarios, the global/local dictionary 110 has access via a data path 111 to the list of routines within the application library, presumably by reading and analyzing it. As depicted, a call via a data path 112 to a routine within the library 109 by the virtual interpreter 113 directly calls the routine in the library, being careful to pass real memory addresses when requested. The advantages of this approach are that the libraries need not be modified, their source programs need not be distributed, and execution speed would be high. The disadvantage is that the application library 109 may corrupt the internals of the virtual program emulator 108. Since the library has direct access to memory used by the emulator, and errant library code could easily disrupt the normal functioning of it through memory over-writes, or continuous looping. In practice, application library support is likely to be achieved through some combination of the above, with in some cases vendors selling altered binary libraries that do extensive checking before preforming function. Various optimizations may be made to the foregoing design. These optimizations address issues of improving processing speed and memory usage. While these would constitute utility improvements to the methods, and involve complexity of design, they are not essential to the basic methods described hereinbefore. Standard Debugging Operations Standard debugging features may be added to the foregoing design. This includes breakpoints, variable monitoring, and memory monitoring. While these would constitute utility improvements to virtual debugging they are not essential to the basic methods described hereinbefore. Saving and Restoring Runtime State Methods for storing and retrieving incompletely assembled runtime states using local or remotely attached storage media is very useful in recreating debugging scenarios in complex debugging situations. The implementation of this feature is achieved by storing in a structured fashion all information currently in the runtime, plus any data dictionary information necessary to reconstruct the state. Retrieval is simply the reverse of the storing logic. A simple resetting of the virtual interpreter would complete the setting of the debug state to what it was at the time it was stored. Now that the invention has been described by way of a preferred embodiment, with alternatives, various modifications and improvements will occur to those of skill in the art. Thus, it should be understood that the detailed description has been provided as an example and not as a limitation. The proper scope of the invention is defined by the claims.
|
Same subclass Same class Consider this |
||||||||||
