Hi,
I think this is a very interesting subject. So far two solutions have
been proposed:
(a) if (sm != null) { sm.XXX(); }
(b) try { sm.XXX(); } catch (NullPointerException e){}
I'd like to propose a third solution. It requires more programming and
results in a larger binary, but on a JIT compiler (such as the one I'm
working on) it may yield the fastest translated code with the lowest
translation/optimisation overhead.
Instead of initialising sm to null I'd like to propose that sm is
initialised to a default object that is a sub class of
SecurityManager. This object doesn't do anything it's merely there to
clear up the confusion caused by having a null object.
The reason this may yield better results is from inlining within the
JIT. If we assume inlining of virtual methods produces code that looks
like a switch statement:
switch (sm){
case null: throw new NullPointerException();
case sm1: { /* body of method XXX for SecurityManager of type
sm1 */
... break;
}
case sm2: { /* body of method XXX for SecurityManager of type
sm2 */
... break;
}
...
}
then for (a) we get:
if (sm != null) { switch (sm){ case null: ... } }
further analysis could remove the double comparison.
for (b) we get:
try { switch (sm){ case null:... } }
catch (NullPointerException e) {}
further analysis could place the body of the exception handler in the
null case.
for the third solution we get:
switch (sm){
case null: throw new NullPointerException();
case sm1: ...
case sm2: ...
case default_sm: { /* The empty body of the new default method */ }
...
}
This immediately gives the default case an empty body, unlike (b)
which requires an optimisation to do this. It also doesn't require
analysis looking for double comparisons.
I know this makes a lot of assumptions on the workings of a JIT and on
the target JVM for Classpath. I wanted offer this solution to see what
others opinions are.
Cheers,
-- Ian Rogers
-- Dept. Of Computer Science
-- The University of Manchester