FULL PRODUCT VERSION : java version "1.6.0_15" Java(TM) SE Runtime Environment (build 1.6.0_15-b03-219) Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02-90, mixed mode) FULL OS VERSION : All platforms. A DESCRIPTION OF THE PROBLEM : When resolving exception edges after register allocation, the C1 register allocator may insert spill code at the wrong insertion position due to an off-by-one error. THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : See the file src/share/vm/c1/c1_LinearScan.cpp @ 1840: if (move_resolver.has_mappings()) { // insert moves after first instruction move_resolver.set_insert_position(block->lir(), 1); move_resolver.resolve_and_append_moves(); } The constant 1 here is incorrect, since moves are inserted _after_ the specified index. Index 0 is always a label and the last index is always a branch. Usually the exception handler block has some instructions, but if it is empty the moves will be inserted after the branch (index 1) and cause an assertion failure later (in the move optimizer). EXPECTED VERSUS ACTUAL BEHAVIOR : The register allocator should insert moves at the correct position, but it does not. This may produce an assertion error later in the compiler, or may produce incorrect code that fails when catching the exception. REPRODUCIBILITY : This bug can be reproduced rarely. ---------- BEGIN SOURCE ---------- /* * @Harness: java * @Runs: 0 = 0; 1 = 2 */ package jtt.except; public class Except_Synchronized05 { Object field; public static int test(int arg) { Except_Synchronized05 obj = new Except_Synchronized05(); int a = obj.bar(arg) != null ? 1 : 0; int b = obj.baz(arg) != null ? 1 : 0; return a + b; } public synchronized Object bar(int arg) { try { String f = foo1(arg); if (f == null) { field = new Object(); } } catch (NullPointerException e) { // do nothing } return field; } public Object baz(int arg) { synchronized (this) { try { String f = foo1(arg); if (f == null) { field = new Object(); } } catch (NullPointerException e) { // do nothing } return field; } } private String foo1(int arg) { if (arg == 0) { throw null; } return null; } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Fix: change the constant 1 to constant 0 in the above mentioned code (repeated here): src/share/vm/c1/c1_LinearScan.cpp @ 1840: if (move_resolver.has_mappings()) { // insert moves after first instruction move_resolver.set_insert_position(block->lir(), 0); move_resolver.resolve_and_append_moves(); }
|