diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index ab90fed01fe1d65511536d7110c02e1c0a14077b..89b42dc9c6d4a8f1021b7907875e7b4e728952e1 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1592,6 +1592,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { // this happened while running the JCK invokevirtual tests under doit. TKR ciMethod* cha_monomorphic_target = NULL; ciMethod* exact_target = NULL; + Value better_receiver = NULL; if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && !target->is_method_handle_invoke()) { Value receiver = NULL; @@ -1653,6 +1654,18 @@ void GraphBuilder::invoke(Bytecodes::Code code) { ciInstanceKlass* singleton = NULL; if (target->holder()->nof_implementors() == 1) { singleton = target->holder()->implementor(0); + + assert(holder->is_interface(), "invokeinterface to non interface?"); + ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; + // the number of implementors for decl_interface is less or + // equal to the number of implementors for target->holder() so + // if number of implementors of target->holder() == 1 then + // number of implementors for decl_interface is 0 or 1. If + // it's 0 then no class implements decl_interface and there's + // no point in inlining. + if (!holder->is_loaded() || decl_interface->nof_implementors() != 1) { + singleton = NULL; + } } if (singleton) { cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); @@ -1667,7 +1680,9 @@ void GraphBuilder::invoke(Bytecodes::Code code) { CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); c->set_incompatible_class_change_check(); c->set_direct_compare(klass->is_final()); - append_split(c); + // pass the result of the checkcast so that the compiler has + // more accurate type info in the inlinee + better_receiver = append_split(c); } } } @@ -1709,7 +1724,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { } if (!success) { // static binding => check if callee is ok - success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); + success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), better_receiver); } CHECK_BAILOUT(); @@ -3034,7 +3049,7 @@ int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const { } -bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { +bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Value receiver) { // Clear out any existing inline bailout condition clear_inline_bailout(); @@ -3056,7 +3071,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { } else if (callee->is_abstract()) { INLINE_BAILOUT("abstract") } else { - return try_inline_full(callee, holder_known); + return try_inline_full(callee, holder_known, NULL, receiver); } } @@ -3405,7 +3420,7 @@ void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool } -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block, Value receiver) { assert(!callee->is_native(), "callee must not be native"); if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { INLINE_BAILOUT("inlining prohibited by policy"); @@ -3541,6 +3556,9 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBeg Value arg = caller_state->stack_at_inc(i); // NOTE: take base() of arg->type() to avoid problems storing // constants + if (receiver != NULL && par_no == 0) { + arg = receiver; + } store_local(callee_state, arg, arg->type()->base(), par_no); } } @@ -3720,7 +3738,7 @@ bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { // Parse first adapter _last = _block = one; - if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { + if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end, NULL)) { restore_inline_cleanup_info(); block()->clear_end(); // remove appended iff return false; @@ -3729,7 +3747,7 @@ bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { // Parse second adapter _last = _block = two; _state = state_before; - if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { + if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end, NULL)) { restore_inline_cleanup_info(); block()->clear_end(); // remove appended iff return false; diff --git a/src/share/vm/c1/c1_GraphBuilder.hpp b/src/share/vm/c1/c1_GraphBuilder.hpp index 8b8800e7448998ad7902fac71874174f8ce31643..aa8f45fa42da76aa04acadfd75915fcb87a363d3 100644 --- a/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/src/share/vm/c1/c1_GraphBuilder.hpp @@ -337,9 +337,9 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); // inliners - bool try_inline( ciMethod* callee, bool holder_known); + bool try_inline( ciMethod* callee, bool holder_known, Value receiver = NULL); bool try_inline_intrinsics(ciMethod* callee); - bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block = NULL); + bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block, Value receiver); bool try_inline_jsr(int jsr_dest_bci); // JSR 292 support diff --git a/src/share/vm/c1/c1_ValueMap.cpp b/src/share/vm/c1/c1_ValueMap.cpp index aa2bf5af5490942955d5119e5e2b1eb31c5d1c59..1f3152085da1ebae45e5415c667eabac78aa9842 100644 --- a/src/share/vm/c1/c1_ValueMap.cpp +++ b/src/share/vm/c1/c1_ValueMap.cpp @@ -125,6 +125,7 @@ Value ValueMap::find_insert(Value x) { // otherwise it is possible that they are not evaluated f->pin(Instruction::PinGlobalValueNumbering); } + assert(x->type()->tag() == f->type()->tag(), "should have same type"); return f; diff --git a/test/compiler/7090976/Test7090976.java b/test/compiler/7090976/Test7090976.java new file mode 100644 index 0000000000000000000000000000000000000000..84ff20a5dacb169bf1e1d54313a43d6e737c6a41 --- /dev/null +++ b/test/compiler/7090976/Test7090976.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012, 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 7090976 + * @summary Eclipse/CDT causes a JVM crash while indexing C++ code + * + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement Test7090976 + */ + +public class Test7090976 { + + static interface I1 { + public void m1(); + }; + + static interface I2 { + public void m2(); + }; + + static interface I extends I1,I2 { + } + + static class A implements I1 { + int v = 0; + int v2; + + public void m1() { + v2 = v; + } + } + + static class B implements I2 { + Object v = new Object(); + Object v2; + + public void m2() { + v2 = v; + } + } + + private void test(A a) + { + if (a instanceof I) { + I i = (I)a; + i.m1(); + i.m2(); + } + } + + public static void main(String[] args) + { + Test7090976 t = new Test7090976(); + A a = new A(); + B b = new B(); + for (int i = 0; i < 10000; i++) { + t.test(a); + } + } +}