# HG changeset patch # User vkempik # Date 1491927478 -10800 # Node ID dcaab7b518c411e87f1f69776c0d6994d3549fcf # Parent c73c5d205d0a2368225c40f75bd3aa2c8e09a5f8 8173373: C1: NPE is thrown instead of LinkageError when accessing inaccessible field on NULL receiver Summary: Deoptimize if receiver null check of unresolved field access fails to throw NoClassDefFoundError instead of NPE. Reviewed-by: vlivanov diff -r c73c5d205d0a -r dcaab7b518c4 src/share/vm/c1/c1_LIR.cpp --- a/src/share/vm/c1/c1_LIR.cpp Fri Apr 07 02:15:31 2017 +0900 +++ b/src/share/vm/c1/c1_LIR.cpp Tue Apr 11 19:17:58 2017 +0300 @@ -1516,6 +1516,17 @@ append(c); } +void LIR_List::null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null) { + if (deoptimize_on_null) { + // Emit an explicit null check and deoptimize if opr is null + CodeStub* deopt = new DeoptimizeStub(info); + cmp(lir_cond_equal, opr, LIR_OprFact::oopConst(NULL)); + branch(lir_cond_equal, T_OBJECT, deopt); + } else { + // Emit an implicit null check + append(new LIR_Op1(lir_null_check, opr, info)); + } +} void LIR_List::cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, LIR_Opr t1, LIR_Opr t2, LIR_Opr result) { diff -r c73c5d205d0a -r dcaab7b518c4 src/share/vm/c1/c1_LIR.hpp --- a/src/share/vm/c1/c1_LIR.hpp Fri Apr 07 02:15:31 2017 +0900 +++ b/src/share/vm/c1/c1_LIR.hpp Tue Apr 11 19:17:58 2017 +0300 @@ -2153,7 +2153,7 @@ void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); } void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); } - void null_check(LIR_Opr opr, CodeEmitInfo* info) { append(new LIR_Op1(lir_null_check, opr, info)); } + void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false); void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info)); } diff -r c73c5d205d0a -r dcaab7b518c4 src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 07 02:15:31 2017 +0900 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Tue Apr 11 19:17:58 2017 +0300 @@ -1700,8 +1700,10 @@ if (x->needs_null_check() && (needs_patching || MacroAssembler::needs_explicit_null_check(x->offset()))) { - // emit an explicit null check because the offset is too large - __ null_check(object.result(), new CodeEmitInfo(info)); + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching); } LIR_Address* address; @@ -1785,8 +1787,10 @@ obj = new_register(T_OBJECT); __ move(LIR_OprFact::oopConst(NULL), obj); } - // emit an explicit null check because the offset is too large - __ null_check(obj, new CodeEmitInfo(info)); + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching); } LIR_Opr reg = rlock_result(x, field_type); diff -r c73c5d205d0a -r dcaab7b518c4 test/compiler/c1/TestUnresolvedField.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/c1/TestUnresolvedField.jasm Tue Apr 11 19:17:58 2017 +0300 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class compiler/c1/TestUnresolvedField version 52:0 { + public static Method testGetField:"()V" stack 1 locals 1 { + aconst_null; + getfield Field T.f:I; // T does not exist + return; + } + + public static Method testPutField:"()V" stack 2 locals 1 { + aconst_null; + iconst_0; + putfield Field T.f:I; // T does not exist + return; + } +} diff -r c73c5d205d0a -r dcaab7b518c4 test/compiler/c1/TestUnresolvedFieldMain.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/c1/TestUnresolvedFieldMain.java Tue Apr 11 19:17:58 2017 +0300 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8173373 + * @compile TestUnresolvedField.jasm + * @run main/othervm -XX:TieredStopAtLevel=1 -Xcomp + * -XX:CompileCommand=compileonly,compiler.c1.TestUnresolvedField::test* + * compiler.c1.TestUnresolvedFieldMain + */ + +package compiler.c1; + +public class TestUnresolvedFieldMain { + public static void main(String[] args) { + try { + TestUnresolvedField.testGetField(); + } catch (java.lang.NoClassDefFoundError error) { + // Expected + } + try { + TestUnresolvedField.testPutField(); + } catch (java.lang.NoClassDefFoundError error) { + // Expected + } + } +}