diff --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp index a6ba988536004ae8f10e2f7bce4fc6486b357f5b..76086794fbc7b47faecf65429292f4aa24c77aae 100644 --- a/src/share/vm/c1/c1_LIR.cpp +++ b/src/share/vm/c1/c1_LIR.cpp @@ -1516,6 +1516,17 @@ void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr 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 --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp index 19acfb37e6a63a8ed91af28602ded3ea73bfeff8..5f4ee0a413803d06032f0d408891f9c100d9975d 100644 --- a/src/share/vm/c1/c1_LIR.hpp +++ b/src/share/vm/c1/c1_LIR.hpp @@ -2153,7 +2153,7 @@ class LIR_List: public CompilationResourceObj { 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 --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index a954ce4361c1fd3800cdada4cd6237f93dfa1b43..7d23f8c1010713a3a5d631cc03e5e1c4de6b89a1 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1700,8 +1700,10 @@ void LIRGenerator::do_StoreField(StoreField* x) { 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 @@ void LIRGenerator::do_LoadField(LoadField* x) { 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 --git a/test/compiler/c1/TestUnresolvedField.jasm b/test/compiler/c1/TestUnresolvedField.jasm new file mode 100644 index 0000000000000000000000000000000000000000..e6c2ae4de2bfaf0917c9d480d36f3d11ba65a027 --- /dev/null +++ b/test/compiler/c1/TestUnresolvedField.jasm @@ -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 --git a/test/compiler/c1/TestUnresolvedFieldMain.java b/test/compiler/c1/TestUnresolvedFieldMain.java new file mode 100644 index 0000000000000000000000000000000000000000..040f1b17be65f60b517ec30a3ba9d864f27efa61 --- /dev/null +++ b/test/compiler/c1/TestUnresolvedFieldMain.java @@ -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 + } + } +}