This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: -fno-cast-check ?!


Norman Hendrich wrote:

Hello,

with the ugly hack outlined below, I got my simulator to run
as fast under gcj as it does under Hotspot Client (even without method inlining).

As it turned out, my code executes multiple type casts in the
inner loop. Unfortunately, the very simple class hierarchy involved is somewhat of a "worst case" for _Jv_CheckCast.
Eliminating the cast check results in more than 10% speedup.

Cool, thats very interesting. FYI I have long had a plan to improve GCJ's type checking. In many cases where GCJ currently always does a _Jv_CheckCast there is enough compile time knowledge of the type to replace it with a very simple inline check or even eliminate it completely. I agree that the type checks are currently a big performance sink for many applications, and its good to know that your tests confirm this.

Many applications, including every application that uses
the Java Collections API, will execute frequent downcasts. It might therefore be useful to add another "overclocker" command line option to gcj,

gcj -fno-cast-check

that totally eliminates the type checking overhead for those
classes that are believed to be type-safe. What do you think?

Yes I agree ;-)

---- diagnosis: frequently called code sequence in my code

public class A { ... } // base class
public class AA extends A { ... } // direct subclass


public class App {

void innerLoop() {
Iterator iterator = collection.iterator();
while(!done) {
A tmp1 = (A) iterator.next(); // actually gets AA: slow
A tmp2 = (A) iterator.next(); // actually gets AA: slow ...
result = calculateResult( tmp1, tmp2, ... );
}
}
}


Unfortunately, the situation sketched above is a "worst case"
scenario for the current implementation of type cast checking
in libjava/java/lang/natClass.cc.

Each cast results in a call to _Jv_CheckCast(), which checks for a non-null argument and then falls through to _Jv_isAssignableFrom().
This method includes a short-circuit test that checks whether
the target and source classes are the same. But here, they are not (target=A vs. source=AA). This means that the full method is traversed, until finally Per's constant time type checking trick is executed:

// _Jv_isAssignableFrom() ...
else if (source->ancestors != NULL
&& target->ancestors != NULL
&& source->depth >= target->depth
&& source->ancestors[source->depth - target->depth] == target)
return true;
...


Question 2: Is the ordering of the different tests (for array, object, interfaces, primitive types) in _Jv_CheckCast necessary? Perhaps a little reordering would already speed up the frequent case (here, unpacking things from collections).

There are a few subtle ordering dependencies in there. Its possible that there is room for improvement, but we'd have to be careful not to break something. The best solution is to make the compiler smarter because many of those tests can be avoided with compile time knowledge. ie: we know at compile time when we're casting to an interface, etc.

---- gcc/java/expr.c:

static void
expand_java_CHECKCAST (type)
tree type;
{
tree value = pop_value (ptr_type_node);
value = build (CALL_EXPR, promote_type (type),
build_address_of (soft_checkcast_node),
tree_cons (NULL_TREE, build_class_ref (type),
build_tree_list (NULL_TREE, value)),
NULL_TREE);
push_value (value);
}

Question 3: Is this the right place to substitute the tree
when trying to disable the type checks? How do I get a "no operation" tree instead of the checkcast?

Just make it return a NOP_EXPR instead of the CALL_EXPR. See build_java_arraystore_check for an example of a function which does something similar.

regards

Bryce.




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]