-
Bug
-
Resolution: Fixed
-
P3
-
1.3.0
-
merlin
-
generic
-
generic
-
Verified
I am looking at a problem with the piece of code below:
It has an exception handler for the sync. block, with a
range [6, 35[ (i.e., excluding bytecode 35), and the
exception handler starts at 35, for all exceptions
(i.e., the exception class index is 0). I have compiled
the method with the 1.3 javac and with 1.3 oldjavac
and I get the same result regarding the exception
range.
java.lang.ref.Finalizer::add (41 bytes)
-------------------------------------
0 get_static 512
3 store_local_object #1
4 load_local_object #1
5 monitor_enter
6 get_static 256
9 branch_if_null 26
12 load_local_object #0
13 get_static 256
16 put_field 0 <next>
19 get_static 256
22 load_local_object #0
23 put_field 1280 <prev>
26 load_local_object #0
27 set_static 256
30 load_local_object #1
31 monitor_exit
32 branch 40
35 store_local_object #2
36 load_local_object #1
37 monitor_exit
38 load_local_object #2
39 throw_exception
40 return_void
This exception range is wrong if am not mistaken
(Todd concurs): if an exception happens after the
monitorexit, e.g. at bytecode 32, the exception
handler will try to unlock the monitor again
(bytecode 37). This is currently a problem for
C1 (what about C2?), since it assumes that a
goto is a safepoint (even though this one is not
a backward branch) and thus assumes that it
may need to handle an asynchronous exception.
As a consequence, it fails with an assertion when
it tries to establish the fact that the monitor stacks
at bytecode 32 and bytecode 35 correspond (they
are off by one in this case). Anyway, this could
probably be fixed with a "counter-hack" in the
compiler...
However, I am wondering now what the consequences
are for the interpreter: potentially, an asynchronous
exception may be delivered to the interpreter at that
goto, in which case the exception handler would try
to unlock the lock twice and die miserably. I am not
100% sure anymore, how we deliver asynchronous
exceptions to the interpreter, but I think we cause a
safepoint and deliver the exception (need to check).
The second question is: what did the Classic VM do?
Could asynchronous exceptions be delivered at each
bytecode? If so, wouldn't this cause a problem in
this case?
robert.griesemer@Eng 2000-04-03
-------------------------------------------------------
I have isolated the bug with a simple example:
The following program:
public class SyncTest {
int _field;
void access() {
synchronized (this) {
_field = 7;
}
}
public static void main(String [] args) {
SyncTest obj = new SyncTest();
obj.access();
System.out.println(obj._field);
}
}
produces the following code for access with javac (newest version):
(used javap -c SyncTest to decompile the code)
Method void access()
0 aload_0
1 astore_1
2 aload_1
3 monitorenter
4 aload_0
5 bipush 7
7 putfield #2 <Field int _field>
10 aload_1
11 monitorexit
12 goto 20
15 astore_2
16 aload_1
17 monitorexit
18 aload_2
19 athrow
20 return
Exception table:
from to target type
4 15 15 any <<<< WRONG EXCEPTION RANGE
Code generated with oldjavac looks as follows:
Method void access()
0 aload_0
1 astore_1
2 aload_1
3 monitorenter
4 aload_0
5 bipush 7
7 putfield #7 <Field int _field>
10 aload_1
11 monitorexit
12 goto 18
15 aload_1
16 monitorexit
17 athrow
18 return
Exception table:
from to target type
4 10 15 any
The exception range is wrong in the first case (see evaluation);
this seems to be a problem only with javac; not with oldjavac.
It is extremely important that this bug is fixed (see evaluation).
robert.griesemer@Eng 2000-04-03
It has an exception handler for the sync. block, with a
range [6, 35[ (i.e., excluding bytecode 35), and the
exception handler starts at 35, for all exceptions
(i.e., the exception class index is 0). I have compiled
the method with the 1.3 javac and with 1.3 oldjavac
and I get the same result regarding the exception
range.
java.lang.ref.Finalizer::add (41 bytes)
-------------------------------------
0 get_static 512
3 store_local_object #1
4 load_local_object #1
5 monitor_enter
6 get_static 256
9 branch_if_null 26
12 load_local_object #0
13 get_static 256
16 put_field 0 <next>
19 get_static 256
22 load_local_object #0
23 put_field 1280 <prev>
26 load_local_object #0
27 set_static 256
30 load_local_object #1
31 monitor_exit
32 branch 40
35 store_local_object #2
36 load_local_object #1
37 monitor_exit
38 load_local_object #2
39 throw_exception
40 return_void
This exception range is wrong if am not mistaken
(Todd concurs): if an exception happens after the
monitorexit, e.g. at bytecode 32, the exception
handler will try to unlock the monitor again
(bytecode 37). This is currently a problem for
C1 (what about C2?), since it assumes that a
goto is a safepoint (even though this one is not
a backward branch) and thus assumes that it
may need to handle an asynchronous exception.
As a consequence, it fails with an assertion when
it tries to establish the fact that the monitor stacks
at bytecode 32 and bytecode 35 correspond (they
are off by one in this case). Anyway, this could
probably be fixed with a "counter-hack" in the
compiler...
However, I am wondering now what the consequences
are for the interpreter: potentially, an asynchronous
exception may be delivered to the interpreter at that
goto, in which case the exception handler would try
to unlock the lock twice and die miserably. I am not
100% sure anymore, how we deliver asynchronous
exceptions to the interpreter, but I think we cause a
safepoint and deliver the exception (need to check).
The second question is: what did the Classic VM do?
Could asynchronous exceptions be delivered at each
bytecode? If so, wouldn't this cause a problem in
this case?
robert.griesemer@Eng 2000-04-03
-------------------------------------------------------
I have isolated the bug with a simple example:
The following program:
public class SyncTest {
int _field;
void access() {
synchronized (this) {
_field = 7;
}
}
public static void main(String [] args) {
SyncTest obj = new SyncTest();
obj.access();
System.out.println(obj._field);
}
}
produces the following code for access with javac (newest version):
(used javap -c SyncTest to decompile the code)
Method void access()
0 aload_0
1 astore_1
2 aload_1
3 monitorenter
4 aload_0
5 bipush 7
7 putfield #2 <Field int _field>
10 aload_1
11 monitorexit
12 goto 20
15 astore_2
16 aload_1
17 monitorexit
18 aload_2
19 athrow
20 return
Exception table:
from to target type
4 15 15 any <<<< WRONG EXCEPTION RANGE
Code generated with oldjavac looks as follows:
Method void access()
0 aload_0
1 astore_1
2 aload_1
3 monitorenter
4 aload_0
5 bipush 7
7 putfield #7 <Field int _field>
10 aload_1
11 monitorexit
12 goto 18
15 aload_1
16 monitorexit
17 athrow
18 return
Exception table:
from to target type
4 10 15 any
The exception range is wrong in the first case (see evaluation);
this seems to be a problem only with javac; not with oldjavac.
It is extremely important that this bug is fixed (see evaluation).
robert.griesemer@Eng 2000-04-03
- relates to
-
JDK-4324989 [c1 frontend] missing exception handler
- Resolved
-
JDK-4651437 TTY: kill001 test crashes the debuggee VM
- Closed