The GCJ Projects List

What follows is a list of projects that the GCJ community would love to see someone pick up and run with. If you're interested in any of these, be sure to send a note with your questions, ideas or intentions to the java mailing list. Similarly, if you would like to see a project listed here that isn't, send a patch for this HTML file to the java-patches list.

jar support

Modify gcj to obey the constraints layed out by the jar file manifest file.

Benchmark infrastructure

Measuring performance is tricky business. We currently do all our performance measurements in an ad hoc manner. What is needed is some infrastructure we can use to track performance regressions and identify opportunities for improvement.

Bryce McKinlay has put together a list of some benchmarks that run on GCJ. Building some infrastructure around these would be incredibly useful.

Performance improvements

There are a few concrete performance improvements that we already know we want:

  • If an object or array is allocated in static code that is executed at most once (i.e. not in a loop or in a non-private method), then we have the option of pre-allocating the object or array in the static data or bss segment. This is most obviously the right thing to do when the expression is an array brace initializer whose elements are compile-time constants, since then we can initialize the array statically. (This is already implemented.) It also makes sense for array elements that are initialized to link-time constants, such as references to other statically allocated objects, as you might get from a multi-dimensional array brace-initializer.

    It may also make sense to pre-allocate a non-array object. It makes most sense when the object constructor is inlined, especially if it turns out that most or all of the fields get initialized to constants. Even if the constructor is not inlined, it may still make sense to pre-allocate the object if it is being assigned to a static final field: The tradeoff is that you save the space needed for the call to allocate the object, but you use more space if it turns out the class is never initialized.

    Note that if a statically allocated object contains pointer fields then the gc has to know about the object. The cleanest way is to make sure the object header has appropriate flags so that the gc recognizes that the object is static but has pointer fields. There is no need to register the static object with the gc, since if it is live, it will get traversed anyway (typically via the fields table of the declaring class).

Compiler improvements

  • Once we have tree-level inlining, we can use it to sometimes eliminate unnecessary synchronizations. Combined with a simple "no escape" flag, this could also let us further optimize string concatenation without having to introduce a new class in the runtime.
  • When compiling from bytecode, GCJ generates tree nodes as long as it is within a single "statement" - i.e. no branching or side effects. However, any branching or other complications causes RTL to be emitted. This is similar to the historical way the C and C++ front-ends were implemented. Gcc now has support for representing an entire method body as a tree node, and g++ has been converted to do that, because it makes certain optimizations more practical. Gcj already represents an entire method body as a single tree structure when compiling from Java source; we should do the same when compiling from bytecode. To begin with, we can represent control flow using GOTO_EXPR. However, if would be better if we can deduce higher-level structure. I.e. it is easy to generate (COND_EXPR TEST (GOTO_EXPR L1) (GOTO_EXPR L2)), but it would be better though harder to simplify that to a COND_EXPR that does not use GOTO_EXPR. The simplification is probably best done after we have generated a correct but GOTO-based tree representation. For example, if a label is only used once, we can move its code to where the unique GOTO is.
  • Add hooks to gcj and g++ to generate write barriers. This would let us write a precise collector.
  • Do escape analysis to detect method-local and thread-local objects. This can yield a significant performance improvement in some cases.
  • Extend the existing null-pointer patch (for PR 2) to optionally enable it for all method calls and field dereferences. This will let gcj-compiled code work correctly on systems without an MMU.
  • The structure of expand_byte_code in expr.c uses macros in a way that in retrospect looks like a mistake. It should be re-written to be a simple switch statement based on the structure of verify_jvm_instructions in verify.c. (There are actually two switch statements using the magic macros in expr.c - look for the includes of "javaop.def". They should both be re-written, but second one is higher priority.)

Runtime improvements

  • Write a program to convert existing locale data into a format we can use.