[211] in java-interest

home help back first fref pref prev next nref lref last post

Re: goto and switch

daemon@ATHENA.MIT.EDU (Arthur van Hoff)
Wed Jun 7 12:48:08 1995

From: Arthur.Vanhoff@Eng.Sun.COM (Arthur van Hoff)
To: jeremy@sour.sw.oz.au (Jeremy Fitzhardinge)
Date: Wed, 7 Jun 1995 08:35:51 -0800 (PDT)
Cc: java-interest@java.Eng.Sun.COM
In-Reply-To: <199506070857.AA11505@sour.sw.oz.au> from "Jeremy Fitzhardinge" at Jun 7, 95 06:57:05 pm


Hi Jeremy,

> > No. The code is illegal. The case statements are not inside the
> > switch.
> 
> Ah, OK.  Are case statements only allowed in the block immediately
> in the switch?  What's the exact syntax?  Something like:
> 
> switch_statement:
> 	"switch" "(" expr ")"
> 	"{"
> 		( { "case" expr ":" } statement )*
> 	"}"
> ( {} optional, ()* 0 or more)
> 
> The part of the spec about control flow is *very* brief.  I think it could
> do with some fleshing out (particularly the other uses of "break" in
> catch and synchronized).

Check out the language grammar in: 

	http://java.sun.com/1.0alpha3/doc/javaspec_11.html

> > In Java it is possible to know when a variable could be used
> > uninitialized. You have to do fairly sophisticated data flow to
> > make sure...
> 
> You can do a conservative estimate, but you can't do it in general.
> E.g.:
> 
> void foo()
> {
> 	int i;
> 
> 	if (bar())
> 		i = 4;
> 	...
> 	if (biff())	// biff() is always true when bar() is
> 		use(i);
> }
> 
> The compiler can't tell how biff() and bar() work, so it can't be
> sure if the use of i has been initialized.  The best it can do is
> insist that i is unconditionally initialized.  

Right, and that is what the compiler does. If there is any doubt,
emit an error.

> And anyway, the
> runtime has to check this too (or be unaffected either way), so it
> doesn't matter much if the compiler just issues warnings rather
> than errors.

It matters a lot if the compiler emits warnings rather than errors.
The above code will not run because the verifier will catch the same
error and throw an exception. The verifier (and therfore also the compiler)
must be able to prove that the variable is *always* initialized, so that
all runtime checks can be eliminated. There are no runtime checks (other
than those in the verifier) for initialized variables.

> > Right. However, the compiler always generates a constant table entry so
> > that the dependencies can be checked correctly. If you want to make
> > sure that you get all the dependencies right you have to use the
> > -depend flag of the compiler.
> 
> Can you explain further?  The compiler generates copies of the constants
> in the switch statements in the class which the runtime can compare
> with the originals?  

Yes, it generates copies. 

> My concern is that inlining the constants from
> another class is effectively inlining part of the implementation which
> could change between compile time and link time, and therefore
> change the semantics without any obvious errors.

Your concern is a valid concern. The avoid this somewhat the compiler
automatically does dependency checks (it has a build in make). But you
are right that the problems not go away completely.

> -- library.thing --
> class thing {
> 	static final int failed=0;
> 	static final int ok=1;
> 	static final int warning=2;
> 
> 	int is_ok() {
> 	// ...
> 	}
> }
> 
> -- app.thing-user --
> 
> class thing_user {
> 	void x () {
> 		switch(obj.is_ok())
> 		{
> 		case library.thing.ok:	...
> 		case library.thing.warning:	...
> 		}
> 	}
> }
> 
> 
> In this case, does Java handle the case where library.thing's
> implementaion changes which changes the values of the constants?
> If the interface changes (methods or their signatures), then a
> runtime exception can be thrown, there can be no such check for
> constant changes
> 
> So, is this a problem?  Is the answer just "well, don't change the
> interfaces of classes in incompatible ways if you want them to keep
> working?".  Or is there a Java mechanism which I don't understand
> at work here?

The bottom line is that, if you are really concerned about changing
an interface in incompatible ways, then you should not use constants,
use variables instead. We chose to inline constants for efficiency,
this has the unfortunate side effect of making interfaces a little
more brittle. However, it is not obvious whether the alternative would
result in acceptable performance.

> > > BTW, what is tableswitch used for?  Is it just for switches which can
> > > be represented in that form, or is it for something else (exception
> > > catching)?
> > 
> > It is for switches that can be represented that way.
> 
> Why have two bytecodes which are essentially the same?  If the runtime
> can implement a switch as a tableswitch, can't it just look at the
> jump table values and rewrite the bytecode in place to be more
> appropriate (like the appendix A optimisations?).

Good point. 

Have fun,

	Arthur van Hoff (avh@eng.sun.com)
	http://java.sun.com/people/avh/
	Sun Microsystems Inc, M/S UPAL02-301,
	100 Hamilton Avenue, Palo Alto CA 94301, USA
	Tel: +1 415 473 7242, Fax: +1 415 473 7104
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com

home help back first fref pref prev next nref lref last post