Java™ is an object-orientated programming language developed by Sun Microsystems. The Java language is small, simple and portable across platforms and operating systems, both at the source and binary level. This makes the Java programming language very popular on the Internet.
Java's platform, independence and code compaction are the most significant advantages of Java over conventional programming languages. In conventional programming languages, the source code of a program is sent to a compiler which translates the program into machine code or processor instructions. The processor instructions are native to the system's processor. If the code is compiled on an Intel-based system, the resulting program will run only on other Intel-based systems. If it is desired to run the program on another system, the user must go back to the original source code, obtain a compiler for the new processor, and recompile the program into the machine code specific to that other processor.
Java operates differently. The Java compiler takes a Java program and, instead of generating machine code for a specific processor, generates bytecodes. Bytecodes are instructions that look like machine code, but are not specific to any processor. To execute a Java program, a bytecode interpreter takes the Java bytecodes and converts them to equivalent native processor instructions and executes the Java program. The Java bytecode interpreter is one component of the Java Virtual Machine (JVM).
Having the Java programs in bytecode form means that instead of being specific to any one system, the programs can be run on any platform and any operating system as long as a Java Virtual Machine is available. This allows a binary bytecode file to be executable across platforms.
The disadvantage of using bytecodes is execution speed. System-specific programs that run directly on the hardware from which they are compiled run significantly faster than Java bytecodes, which must be processed by the Java Virtual Machine. The processor must both convert the Java bytecodes into native instructions in the Java Virtual Machine and execute the native instructions.
Poor Java software performance, particularly in embedded system designs, is a well-known issue and several techniques have been introduced to increase performance. However these techniques introduce other undesirable side effects. The most common techniques include increasing system and/or microprocessor clock frequency, modifying a JVM to compile Java bytecodes and using a dedicated Java microprocessor.
Increasing a microprocessor's clock frequency results in overall improved system performance gains, including performance gains in executing Java software. However, frequency increases do not result in one-for-one increases in Java software performance. Frequency increases also raise power consumption and overall system costs. In other words, clocking a microprocessor at a higher frequency is an inefficient method of accelerating Java software performance.
Compilation techniques (e.g., just in time “JIT” compilation) contribute to erratic performance because the speed of software execution is delayed during compilation. Compilation also increases system memory usage because compiling and storing a Java program consumes an additional five to ten times the amount of memory over what is required to store the original Java program.
Dedicated Java microprocessors use Java bytecode instructions as their native language, and while they execute Java software with better performance than typical commercial microprocessors they impose several significant design constraints. Using a dedicated Java microprocessor requires the system design to revolve around it and forces the utilization of specific development tools usually only available from the Java microprocessor vendor. Furthermore, all operating system software and device drivers must be custom developed from scratch because commercial software of this nature does not exist.
It is desired to have an embedded system with improved Java software performance.
One embodiment of the present invention comprises a system including at least one memory, a processor chip operably connected to the one memory, and an Accelerator Chip. The memory access for the processor chip to at least one memory being sent through the Accelerator Chip. The Accelerator Chip has direct access to the at least one memory. The Accelerator Chip is adapted to run at least portions of programs using intermediate language instructions. The intermediate language instructions include Java bytecodes and also include the intermediate language forms of other interpreted languages. These intermediate language forms include Multos bytecodes, UCSD Pascal P-codes, MSIL for C#/.NET and other instructions. While the present invention is for any intermediate language, Java will be referred to for examples and clarification.
By using an Accelerator Chip, systems with conventional processor chips and memory units can be accelerated for processing intermediate language instructions such as Java bytecodes. The Accelerator Chip is preferably placed in the path between the processor chip and the memory and can run intermediate language programs very efficiently. In a preferred embodiment, the Accelerator Chip includes a translator unit which translates at least some intermediate language instructions and an execution engine to execute the translated instructions. Execution of multiple intermediate languages can be supported in one accelerator concurrently or sequentially. For example, in one embodiment, the accelerator executes Java bytecodes as well as MSIL for C#/.NET.
Another embodiment of the present invention comprises an Accelerator Chip including a unit to execute intermediate language instructions, such as Java bytecodes and a memory interface. The memory interface is adapted to allow for memory access for the Accelerator Chip to at least one memory and to allow memory access to a separate processor chip to the at least one memory. By having an Accelerator Chip with such a memory interface, the Accelerator Chip can be placed in the path between the processor chip and memory unit.
Another embodiment of the present invention comprises an Accelerator Chip including a hardware translator unit, an execution engine, and a memory interface.
In another embodiment of the present invention, an intermediate language instruction cache operably connected to the hardware translator unit is used. By storing the intermediate language instructions in the cache, the execution speed of the programs can be significantly improved.
Another embodiment of the present invention comprises an Accelerator Chip including a hardware translator unit adapted to convert intermediate language instructions into native instructions, and a dedicated execution engine, the dedicated execution engine adapted to execute native instructions provided by the hardware translator unit. The dedicated execution engine only executing instructions provided by the hardware translator unit. The hardware translator unit rather than the execution engine preferably determines the address of the next intermediate language instructions to translate and provide to the dedicated execution engine. Alternatively the execution engine can determine the next address for the intermediate language instructions.
In one embodiment, the hardware translator unit only translates some intermediate language instructions, other intermediate language instructions cause a callback to the processor chip that runs a virtual machine to handle these exceptional instructions.
As will be described below, the Accelerator Chip 22 is preferably placed within the path between the processor chip 26 and memory units 24. The Accelerator Chip 22 runs at least portions of programs, such as Java, in an accelerated manner to improve the speed and reduce the power consumption of the entire system. In this embodiment, the Accelerator Chip 22 includes an execution unit 32 to execute intermediate language instructions, and a memory interface unit 30. The memory interface unit 30 allows the execution unit 32 on the Accelerator Chip 22 to access the intermediate language instructions and data to run the programs. Memory interface 30 also allows the processor chip 26 to obtain instructions and data from the memory units 24. The memory interface 30 allows the Accelerator Chip to be easily integrated with existing chip sets (SOC's). The accelerator function can be integrated as a whole or in part on the same chip stack package or on the same silicon with the SOC. Alternatively, it can be integrated into the memory as a chip stack package or on the same silicon.
The execution unit portions 32 of the Accelerator Chip 22 can be any type of intermediate language instruction execution unit. For example, in one embodiment a dedicated processor for the intermediate language instructions, such as a dedicated Java processor, is used.
In a preferred embodiment, however, the intermediate language instruction execution unit 32 comprises a hardware translator unit 34 which translates intermediate language instructions into translated instructions for an execution engine 36. The hardware translator unit 34 efficiently translates a number of intermediate language instructions. In one embodiment, the processor chip 26 handles certain intermediate language instructions which are not handled by the hardware translator unit. By having the translator unit efficiently translate some of the intermediate language instructions, then having these translated instructions executed by an execution engine, the speed of the system can be significantly increased. The translator can be microcode based, hence allowing the microcode to be swapped for Java versus C#/.NET.
Running a virtual machine completely in the processor 26 has a number of disadvantages. The translation portion of the virtual machine interpreter tends to be quite large and can be larger than the caches used in the processor chips. This causes the portions of the translating code to be repeatedly brought in and out of the cache from external memory, which slows the system. The translator unit 34 on the Accelerator Chip 22 does the translation without requiring translation software transfer from an external memory unit. This can significantly speed the operation of the intermediate language programs.
The use of callbacks for some intermediate language instructions is useful because it can reduce the size and power consumption of the Accelerator Chip 22. Rather than having a relatively complicated execution unit that can execute every intermediate language instruction, translating only certain intermediate language instructions in the translation unit 34 and executing them in the execution engine 36 reduces the size and power consumption of the Accelerator Chip 22. The intermediate language instructions executed by the accelerator are preferably the most commonly used instructions. The intermediate language instructions not executed by the accelerator chip can be implemented as callbacks such that they are executed on the SoC. Alternatively, the Accelerator Chip of one embodiment can execute every intermediate language instruction.
Also shown in the execution unit 32 of one embodiment is an interface unit and registers 42. In a preferred embodiment, the processor chip 26 runs a modified virtual machine which is used to give instructions to the Accelerator Chip 22. When a callback occurs, the translator unit 34 sets a register in unit 42 and the execution unit restores all the elements that need restoring and indicates such in the unit 42. In a preferred embodiment, the processor chip 26 has control over the Accelerator Chip 22 through the interface unit and registers 42. The execution unit 32 operates independently once the control is handed over to the Accelerator Chip.
In a preferred embodiment, an intermediate language instruction cache 38 is used associated with the translator unit 34. Use of an intermediate language instruction cache further speeds up the operation of the system and results in power savings because the intermediate language instructions need not be requested as often from the memory units 24. The intermediate language instructions that are frequently used are kept in the instruction cache 38. In a preferred embodiment, the instruction cache 38 is a two-way associative cache. Also associated with the system is a data cache 40 for storing data.
Although the translator unit is shown in
The intermediate language instructions are preferably Java bytecodes. Note that other intermediate language instructions, such as Multos bytecodes, MSIL, BREW, etc., can be used as well. For simplicity, the remainder of the specification describes an embodiment in which Java is used, but other intermediate language instructions can be used as well.
In a preferred embodiment, the execution engine 36′ is dedicated to only execute the translated instructions from the Java translating unit. In a preferred embodiment, processor 60 is a reduced instruction set computing (RISC) processor or a DSP, or VLIW or CISC processor. These processors can be customized or modified so its instruction set is designed to efficiently execute the translated instructions. Instructions and features that are not needed are preferably removed from the instruction set of the execution engine to produce a simpler execution engine—for example, interrupts are preferably not used. Furthermore, the execution engine 36′ need not directly calculate the location of the next instruction to execute. The Java translator unit 34′ can instead calculate the addresses of the next Java bytecode to translate. The processor 60 produces flags to controller 62 which then calculates the location of the next Java bytecode to translate. Alternatively, standard processors can be used.
In one embodiment, the bytecode buffer control unit 72 checks how many bytecode bytes are accepted into the Java translator, and modifies the Java program counter 70. The controller 62 can also modify the Java program counter. The address unit 64 obtains the next instruction either from the instruction cache or from external memory. Note that, for example, the controller 62 can also clear out the Java translator unit's pipeline if required by a “branch taken” or a callback. Data from the processor 60 is also stored in the data cache 68.
When the virtual machine modifies the bytecode to the quick form, the cache line in the hardware accelerator holding the bytecode being modified needs to be invalidated. The same is true when the virtual machine reverses this process and restores the bytecode to the original form. Additionally, the callbacks invalidate the appropriate cache line in the instruction cache using a cache invalidate register in the interface register.
In some embodiments, when quick bytecodes are used, the modified instructions are stored back into the instruction cache 52. When quick bytecodes are used, the system must keep track of how the Java bytecodes are modified and eventually have instruction consistency between the cache and the external memory.
In one embodiment, the decoded bytecodes from the bytecode decode unit are sent to a state machine unit and Arithmetic Logic Unit (ALU) in the instruction composition unit 54. The ALU is provided to rearrange the bytecode instructions to make them easier to be operated on by the state machine and perform various arithmetic functions including computing memory references. The state machine converts the bytecodes into native instructions using the lookup table. Thus, the state machine provides an address which indicates the location of the desired native instruction in the microcode look-up table. Counters are maintained to keep a count of how many entries have been placed on the operand stack, as well as to keep track of and update the top of the operand stack in memory and in the register file. In a preferred embodiment, the output of the microcode look-up table is augmented with indications of the registers to be operated on in the register file. The register indications are from the counters and interpreted from bytecodes. To accomplish this, it is necessary to have a hardware indication of which operands and variables are in which entries in the register file. Native Instructions are composed on this basis. Alternately, these register indications can be sent directly to the register file.
In another embodiment of the present invention, the Stack and Variable manager assigns Stack and Variable values to different registers in the register file. An advantage of this alternate embodiment is that in some cases the Stack and Var values may switch due to an Invoke Call and such a switch can be more efficiently done in the Stack and Var manager rather than producing a number of native instructions to implement this.
In one embodiment, a number of important values can be stored in the hardware accelerator to aid in the operation of the system. These values stored in the hardware accelerator help improve the operation of the system, especially when the register files of the execution engine are used to store portions of the Java stack.
The hardware translator unit preferably stores an indication of the top of the stack value. This top of the stack value aids in the loading of stack values from the memory. The top of the stack value is updated as instructions are converted from stack-based instructions to register-based instructions. When instruction level parallelism is used, each stack-based instruction which is part of a single register-based instruction needs to be evaluated for its effects on the Java stack.
In one embodiment, an operand stack depth value is maintained in the hardware accelerator. This operand stack depth indicates the dynamic depth of the operand stack in the execution engine register files. Thus, if eight stack values are stored in the register files, the stack depth indicator will read “8.” Knowing the depth of the stack in the register file helps in the loading and storing of stack values in and out of the register files.
Additionally, a frame stack can be maintained in the hardware with its own underflow/overflow and frame depth indication to indicate how many frames are on the frame stack. The frame stack can be a stand-alone stack or incorporated within the CPU's register file. In a preferred embodiment, the frame stack and the operand stack can be within the same register file of the CPU. In another embodiment, the frame stack and the operand stack are different entities. The local variables would also be stored in a separate area of the CPU register file which also has the operand stack and/or the frame stack.
In a preferred embodiment, a minimum stack depth value and a maximum stack depth value are maintained by the hardware translator unit. The stack depth value is compared to the required maximum and minimum stack depths. When the stack value goes below the minimum value, the hardware translator unit composes load instructions to load stack values from the memory into the register file. When the stack depth goes above the maximum value, the hardware translator unit composes store instructions to store stack values back out to the memory.
In one embodiment, at least the top eight (8) entries of the operand stack in the execution engine register file operate as a ring buffer, and the ring buffer is maintained in the accelerator and is operably connected to a overflow/underflow unit.
The hardware translator unit also preferably stores an indication of the operands and variables stored in the register file of the execution engine. These indications allow the hardware accelerator to compose the converted register-based or native instructions from the incoming stack-based instructions.
The hardware translator unit also preferably stores an indication of the variable base and operand base in the memory. This allows for the composing of instructions to load and store variables and operands between the register file of the execution engine and the memory. For example, when a variable (Var) is not available in the register file, the hardware issues load instructions. The hardware is adapted to multiply the Var number by four and adding the Var base to produce the memory location of the Var. The instruction produced is based on knowledge that the Var base is in a temporary native execution engine register. The Var number times four can be made available as the immediate field of the native instruction being composed, which may be a memory access instruction with the address being the content of the temporary register holding a pointer to the Vars base plus an immediate offset. Alternatively, the final memory location of the Var may be read by the execution engine as an instruction and then the Var can be loaded.
In one embodiment, the hardware translator unit marks the variables as modified when updated by the execution of Java bytecodes. The hardware accelerator can copy variables marked as modified to the system memory for some bytecodes.
In one embodiment, the hardware translator unit composes native instructions wherein the native instruction's operands contain at least two native execution engine register file references where the register file contents are the data for the operand stack and variables.
In one embodiment a stack-and-variable-register manager maintains indications of what is stored in the variable and stack registers of the register file of the execution engine. This information is then provided to the decode stage and microcode stage in order to help in the decoding of the Java bytecode and generating appropriate native instructions.
In a preferred embodiment, one of the functions of a Stack-and-Var register manager is to maintain an indication of the top of the stack. Thus, if for example registers R1-R4 store the top 4 stack values from memory or by executing bytecodes, the top of the stack will change as data is loaded into and out of the register file. Thus, register R2 can be the top of the stack and register R1 be the bottom of the stack in the register file. When a new data is loaded into the stack within the register file, the data will be loaded into register R3, which then becomes the new top of the stack, the bottom of the stack remains R1. With two more items loaded on the stack in the register file, the new top of stack in the register file will be R1 but first R1 will be written back to memory by the accelerator's overflow/underflow unit, and R2 will be the bottom of the partial stack in the register file.
The Accelerator Chip has direct access to the system SRAM and/or Flash memory. The host microprocessor (or microprocessor within an SOC) has transparent access to the system SRAM or Flash memory through the Accelerator Chip (“the system memory is behind the accelerator”).
The Accelerator Chip preferably synchronizes with the host microprocessor via a monitor within its companion software kernel. The Software Kernel (or the processor chip) loads specific registers in the accelerator chip with the address of where Java bytecode instructions are located, and then transfers control to the accelerator chip to begin executing. The software kernel then waits in a polling loop running on the host microprocessor reading the run mode status until either it detects that it is necessary to process a bytecode using the callback mechanism or until all bytecodes have been executed. The polling loop can be implemented by reading the “run mode” pin electrically connected between the accelerator chip and a general purpose I/O pin on the SOC. Alternatively, the same status of the “run mode” can be polled by reading the registers within the accelerator chip. In either of these cases, the accelerator chip automatically enters its power-saving sleep state until callback processing has completed or it is directed to execute more bytecodes.
The Accelerator Chip fetches the entire Java bytecode including the operands from memory, through its internal caches, and executes the instruction. Instructions and data resident in the caches are executed faster and at reduced power consumption because system memory transactions are avoided. Bytecode streams are buffered and analyzed prior to being interpreted using an optimizer based on instruction level parallelism (ILP). The ILP optimizer coupled with locally cached Java data results in the fastest execution possible for each cycle.
Since the Accelerator Chip is a separate stand-alone Java bytecode execution engine, it processes concurrently while the host microprocessor is either waiting in its polling loop or processing interrupts. Furthermore, the Accelerator Chip is only halted during instances when the host microprocessor needs to access system memory behind it, and the accelerator chip also wants to access system memory at the same time. For example, if the host microprocessor is executing an interrupt service routine or other software from within its own cache, then the Accelerator Chip can concurrently execute bytecodes. Similarly, if Java bytecode instructions and data reside within the Accelerator Chip's internal caches, then the accelerator can concurrently execute bytecodes even if the host microprocessor needs to access system memory behind it.
Once activated, the Accelerator Chip runs until any of the following events occurs:
The Accelerator Chip is disabled (in its sleep mode) and transparent to all native resident software by default, and it is enabled when a modified Java virtual machine initializes it and calls on it to execute Java bytecode instructions. When the accelerator chip is in its sleep mode, accesses to SRAM or Flash memory from the host microprocessor simply pass through the Accelerator chip.
The Accelerator Chip includes a memory controller as an integral part of its memory interface circuitry that needs to be programmed in a manner typical of SRAM and/or Flash memory controllers. The actual programming is done within the software kernel with the specific memory addresses set according to each device's unique architecture and memory map. As part of the modified Java virtual machine's initialization sequence, registers within accelerator chip arc loaded with the appropriate information. When the system calls on its JVM to execute Java software, it first loads the address of the start of the Java bytecodes into the Java Program Counter (JP) of the Accelerator Chip. The kernel then begins running on the host microprocessor monitoring the Accelerator Chip for when it signals that it has completed executing Java bytecodes. Upon completion the Accelerator Chip goes into its sleep mode and its kernel returns control to the JVM and the system software.
The Accelerator chip does not disturb interrupt or exception processing, nor does it impose any latency. When an interrupt or exception occurs while the Accelerator Chip is processing, the host microprocessor diverts to an appropriate handler routine without affecting accelerator chip. Upon return from the handler, the host microprocessor returns execution to the software kernel and in turn resumes monitoring the Accelerator Chip. Even when the host microprocessor takes over the memory bus, the Accelerator Chip can continue executing Java bytecodes from its internal cache, which can continue so long as a system memory bus conflict does not arise. If a conflict arises, a stall signal can be asserted to halt the accelerator.
The Accelerator Chip has several shared registers that are located in its memory map at a fixed offset from a programmable base. The registers control its operation and are not meant for general use, but rather are handled by code within the Software Kernel.
Referring to
The operating system running on the host microprocessor is preferably set up such that virtual memory equals real memory for all areas of memory that the accelerator chip will access as part of its Java processing.
Integration with a Java virtual machine is preferably accomplished through the modifications as listed below.
One embodiment of the Accelerator Chip preferably interfaces with any system that has been designed with asynchronous SRAM and/or asynchronous Flash memory including page mode Flash memory. In such circumstances, the accelerator chip easily integrates because it looks to the system like an SRAM or Flash device. No other accommodations are necessary for integration. The Accelerator Chip has its own memory controller and correspondingly the ability to access memory “behind the accelerator” directly via an internal program counter (IPC). As with any program counter, the JP points to the address of the next instruction to be fetched and executed. This allows the accelerator chip to operate asynchronously and concurrently with regard to the host microprocessor.
In a preferred embodiment, the pins going to the processor chip and going to the memory are located near each other in order to keep the delay through the chip at the minimum for the bypass mode.
The adder/subtractor unit 172 produces a result and also produces the N, Z and C bits which are sent to the N, Z and C logic 174. For the hounds checking case, the bounds checking logic 176 checks to see whether the index is inside the size of the array. In the bounds checking, the index value is subtracted from the array size, the index value will be stored in one register, while the array value is stored in another register. If there is a carry, this indicates an exception, and the bounds check logic 176 produces an index out of range exception when the bounds checking is enabled.
Logical unit 178 includes the new logic 180. This new logic 180 implements the SGTLT0 and SGTLT0U instructions. Logic 180 uses the N and Z carry bits from a previous subtraction or add. As illustrated by
In
The hardware translator is enabled to translate into the above new instructions. This makes the translation from Java bytecodes more efficient.
The Accelerator Chip of the present invention has a number of advantages. The Accelerator Chip directly accesses system memory to execute Java bytecode instructions while the host microprocessor services its interrupts, contributing to speed-up of Java software execution. Because the accelerator chip executes bytecodes and does not compile them, it does not impose additional memory requirements, making it a less costly and more efficient solution than using ahead-of-time (AOT) or just-in-time (JIT) compilation techniques. System level energy usage is minimized through a combination of faster execution time, reduced memory accesses and power management integrated within the accelerator chip. When not executing bytecodes, the Accelerator Chip is automatically in its power-saving sleep mode. The accelerator chip uses data localization and instruction level parallelism (ILP) optimizations achieve maximum performance. Data held locally within the accelerator chip preferably includes top entries on the Java stack and local variables that increase the effectiveness of the ILP optimizations and reduce accesses to system memory. These techniques result in fast and consistent execution and reduced system energy usage. This is in contrast to typical commercial microprocessors that rely on software interpretation that treat bytecodes as data and therefore derive little to no benefit from their instruction cache. Also, because Java bytecodes along with their associated operands vary in length a typical software bytecode interpreter must perform several data accesses from memory to complete each Java bytecode fetch cycle—a process that is inefficient in terms of performance and power consumption. The Java Virtual Machine (JVM) is a stack-based machine and most software interpreters locate the entire Java stack in system memory requiring several costly memory transactions to execute each Java bytecode instruction. As with bytecode fetches, the memory transactions required to manage and interact with a memory based Java stack are costly in terms of performance and increased system power consumption.
The Accelerator Chip easily interfaces directly to typical memory system designs and is fully transparent to all system software providing its benefits without requiring any porting or new development tools. Although the JVM is preferably modified to drive Java bytecode execution into the accelerator chip, all other system components and software are unaware of its presence. This allows any and all commercial development tools, operating systems and native application software to run as-is without any changes and without requiring any new tools or software. This also preserves the investment in operating system software, resident applications, debuggers, simulators or other development tools. Introduction of a accelerator chip is also transparent to memory accesses between the host microprocessor and the system memory but may introduce wait states. The Accelerator Chip is useful for mobile/wireless handsets, PDAs and other types of Internet Appliances where performance, device size, component cost, power consumption, case of integration and time to market are critical design considerations.
In one embodiment, the accelerator chip is integrated as a chip stack with the processor chip. In another embodiment, the accelerator chip is on the same silicon as the memory. Alternatively, the accelerator chip is integrated as a chip stack with the memory. In a further embodiment, the processor chip is a system on a chip. In an alternative embodiment, the system on a chip is adapted for use in cellular phones.
In one embodiment, the decelerator chip supports execution of two or more intermediate languages, such as Java bytecodes and MSIL for C#/.NET.
In one embodiment of the present invention, the system comprises at least one memory, a processor chip operably connected to the at least one memory, and an accelerator chip, the accelerator chip operably connected to the at least one memory, memory access of the processor chip to the at least one memory being sent through the accelerator chip, the accelerator chip having direct access to the at least one memory, the accelerator chip being adapted to run at least portions of programs in an intermediate language, the hardware accelerator including a accelerator of a Java processor for the execution of intermediate language instructions.
In a further embodiment of the present invention, the system comprises at least one memory, a processor chip operably connected to the at least one memory, and an intermediate language accelerator chip, operably connected to the at least one memory, memory access of the processor chip to the at least one memory being sent through the accelerator chip, the accelerator chip having direct access to the at least one memory, the accelerator chip being adapted to run at least portions of programs in an intermediate language, wherein some instructions generate a callback and get executed on the processor chip.
The present application incorporates by reference application Ser. No. 09/208,741 filed Dec. 8, 1998; application Ser. No. 09/488,186 filed Jan. 20, 2000; application No. 60/239,298 filed Oct. 10, 2000; application Ser. No. 09/687,777 filed Oct. 13, 2000; application Ser. No. 09/866,508 filed May 25, 2001; application No. 60/302,891 filed Jul. 2, 2001; and application Ser. No. 09/938,886 filed Aug. 24, 2001.
While the present invention has been described with reference to the above embodiments, this description of the preferred embodiments and methods is not meant to he construed in a limiting sense. For example, the term Java in the specification or claims should be construed to cover successor programming languages or other programming languages using basic Java concepts (the use of generic instructions, such as bytecodes, to indicate the operation of a virtual machine). It should also be understood that all aspects of the present invention are not to be limited to the specific descriptions, or to configurations set forth herein. Some modifications in form and detail the various embodiments of the disclosed invention, as well as other variations in the present invention, will be apparent to a person skilled in the art upon reference to the present disclosure. It is therefore contemplated that the following claims will cover any such modifications or variations of the described embodiment as falling within the true spirit and scope of the present invention.
The present application is related to Application No. 60/306,376 filed Jul. 17, 2001, which is incorporated herein by reference.
Number | Date | Country | |
---|---|---|---|
Parent | 10187858 | Jun 2002 | US |
Child | 13207168 | US |