24-Nov-2000
Ralf Kleberhoff ( kleberhoff@aol.com
)
Watch the newsgroup pilot.programmer.jump on the server news.massena.com.
The current version can be found at http://sourceforge.net/projects/jump
WARNING
Jump2 is still in an Alpha state of development. Don't expect a stable development environment. Jump2 might notwork as expected. Don't blame me if something goes wrong - you have been warned...
This is a major cleanup release. The most important aspects are:
Besides that, some minor bugs have been fixed.
Detailed information can be found in the Jump2 Development Notes.
Type | Description | Status |
Limitation | The Java PilotMain() method
won't receive launch codes other than 0 (normal launch). Reason: PalmOS calls an application's PilotMain function in many situations without an explicit request by the user -- but these calls use launch codes different from 0. As Jump2 can possibly crash even before calling the Java PilotMain() method, I decided to handle anything but a normal launch in the safest possible way: an immediate return. |
introduced 05-Jun-00 with Alpha2 |
Limitation | Jump seems to have problems with JDK 1.1.x. | reported 05-Jul-00 for Alpha3 |
Limitation | Jump now has problems with JDK 1.3 (String class incompatible) | solved (?) Alpha8 |
Limitation | Jump only checks for not-compiler-detectable Runtime Exceptions (e.g. ClassCastException), but not Linking Exceptions (e.g. NoSuchMethodError). Programs that pass the compiler correctly, normally can't generate certain types of exceptions (e.g. Linking Exceptions), so I decided to omit these checks. If you carelessly mix classfiles from incompatible sources, Jump will behave strangely. | permanent limitation |
Limitation | Jump doesn't have Threads. | permanent limitation |
Limitation | Class initializer code isn't called exactly at the right moment. If you rely on a specific sequence between class initializers and methods from other classes, Jump won't work. All class initializers are called in sequence before the main program starts. | permanent limitation |
Jump2 contains some optimizations on the conceptual level, but not yet a peep-hole optimizer for the resulting assembly code :-(.
In object-oriented languages, when you call a method on some object, there are normally many different implementations of this method in different classes. The decision which one to call actually, is made during run-time, based on the run-time type of the object. Traditionally, so-called "virtual function tables" ("vtables") are used.
On the other hand, as a programmer, you can often tell exactly which method implementation will be called in a given place, meaning that a vtable for this call isn't necessary, a direct call of that method is O.K. too.
Jump2 contains an optimization that tries to find those situations where a vtable-based method call can be replaced by a simple direct function call.
To do this, we need to know whether a given class has instances or not. If there is a method call for method M in class C, we collect all subclasses of C (plus C itself) having instances. For all of these classes with instances, we search upwards the class tree to find the method implementation that applies to this class. If we always find the very same implementation, we can simply generate a direct call of that implementation. If we find more than one implementation, we really need a vtable.
In practice, vtables can be eliminated in many method calls, see the following examples:
As I said, we need to know which classes have instances. We can find it out by looking for places where new instances are created (JVM instructions like 'new', 'newarray' and so on). Some objects (namely exceptions) can be created by the Java runtime system without a specific 'new' instruction, so we have to mark some exception classes as "having instances" too.
In principle, the 'instanceof' operator requires a JVM to search the class tree / class graph upwards along superclasses, interfaces and superinterfaces. Jump replaces this searching process by a simple table lookup. For the fixed set of classes of a single program, Jump builds a boolean matrix, where a 1 at (c1,c2) means that an instance of class c1 is 'instanceof' a class c2. So, a single bit-array access decides the 'instanceof' relation.
The matrix is sparse, some rows and columns are completely eliminated:
This allows for a compact implementation of the matrix.
According to the JVM specification, class initializer methods are called automatically by the JVM before a class is used for the first time (the exact definition of "being used" in this context is a bit complicated). For any class needing static initializations we find a single static method named <clinit>. This method contains instructions to set static fields of that class to initial values, together with any code from 'static { ... }' sections in the class definition.
All these distinct initializations are merged into a single initializer method by the Java compiler :-(. We can't completely exclude <clinit> methods, as the Java 1.2 class library needs them, but if we include them completely, we get nearly the whole library into even the smallest programs, because some part of the <clinit> method needs some other class that also has a <clinit> method, and so on.
So, I decided to introduce a "needed"-flagging on the single-instruction level for <clinit> methods. This flagging follows these guidelines:
I also implemented 2 potentially dangerous optimizations:
A future version of Jump2 will make these optimizations user-switchable.
Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.