# HG changeset patch # User bharadwaj # Date 1398450587 14400 # Node ID 1cad13fb2969f2fe0e28deb60850dc70a365d386 # Parent 47f5725e0d7ca0ffe6a0113663aea3792ce70b0f# Parent b66e3734cb3ff10dba0f4bca82000a1f6efc0b8c Merge diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -3152,10 +3152,12 @@ // if fast computation is not possible, result is NaN. Requires // fallback from user of this macro. // increase precision for intermediate steps of the computation + BLOCK_COMMENT("fast_pow {"); increase_precision(); fyl2x(); // Stack: (Y*log2(X)) ... pow_exp_core_encoding(); // Stack: exp(X) ... restore_precision(); + BLOCK_COMMENT("} fast_pow"); } void MacroAssembler::fast_exp() { diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -1701,6 +1701,15 @@ return NULL; } +void GraphBuilder::check_args_for_profiling(Values* obj_args, int expected) { +#ifdef ASSERT + bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); + assert(expected == obj_args->length() || real_target->is_method_handle_intrinsic(), "missed on arg?"); +#endif +} + // Collect arguments that we want to profile in a list Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) { int start = 0; @@ -1709,13 +1718,14 @@ return NULL; } int s = obj_args->size(); - for (int i = start, j = 0; j < s; i++) { + // if called through method handle invoke, some arguments may have been popped + for (int i = start, j = 0; j < s && i < args->length(); i++) { if (args->at(i)->type()->is_object_kind()) { obj_args->push(args->at(i)); j++; } } - assert(s == obj_args->length(), "missed on arg?"); + check_args_for_profiling(obj_args, s); return obj_args; } @@ -3847,14 +3857,7 @@ j++; } } -#ifdef ASSERT - { - bool ignored_will_link; - ciSignature* declared_signature = NULL; - ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); - assert(s == obj_args->length() || real_target->is_method_handle_intrinsic(), "missed on arg?"); - } -#endif + check_args_for_profiling(obj_args, s); } profile_call(callee, recv, holder_known ? callee->holder() : NULL, obj_args, true); } diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/c1/c1_GraphBuilder.hpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Fri Apr 25 14:29:47 2014 -0400 @@ -392,6 +392,7 @@ Values* args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver); Values* collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver); + void check_args_for_profiling(Values* obj_args, int expected); public: NOT_PRODUCT(void print_stats();) diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -2636,8 +2636,10 @@ // LIR_Assembler::emit_profile_type() from emitting useless code profiled_k = ciTypeEntries::with_status(result, profiled_k); } - if (exact_signature_k != NULL && exact_klass != exact_signature_k) { - assert(exact_klass == NULL, "obj and signature disagree?"); + // exact_klass and exact_signature_k can be both non NULL but + // different if exact_klass is loaded after the ciObject for + // exact_signature_k is created. + if (exact_klass == NULL && exact_signature_k != NULL && exact_klass != exact_signature_k) { // sometimes the type of the signature is better than the best type // the compiler has exact_klass = exact_signature_k; @@ -2648,8 +2650,7 @@ if (improved_klass == NULL) { improved_klass = comp->cha_exact_type(callee_signature_k); } - if (improved_klass != NULL && exact_klass != improved_klass) { - assert(exact_klass == NULL, "obj and signature disagree?"); + if (exact_klass == NULL && improved_klass != NULL && exact_klass != improved_klass) { exact_klass = exact_signature_k; } } diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -2284,13 +2284,13 @@ void nmethodLocker::lock_nmethod(nmethod* nm, bool zombie_ok) { if (nm == NULL) return; Atomic::inc(&nm->_lock_count); - guarantee(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method"); + assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method"); } void nmethodLocker::unlock_nmethod(nmethod* nm) { if (nm == NULL) return; Atomic::dec(&nm->_lock_count); - guarantee(nm->_lock_count >= 0, "unmatched nmethod lock/unlock"); + assert(nm->_lock_count >= 0, "unmatched nmethod lock/unlock"); } diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/code/nmethod.hpp Fri Apr 25 14:29:47 2014 -0400 @@ -203,7 +203,7 @@ // and is not made into a zombie. However, once the nmethod is made into // a zombie, it will be locked one final time if CompiledMethodUnload // event processing needs to be done. - jint _lock_count; + volatile jint _lock_count; // not_entrant method removal. Each mark_sweep pass will update // this mark to current sweep invocation count if it is seen on the diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -222,7 +222,7 @@ bool inline_math_subtractExactL(bool is_decrement); bool inline_exp(); bool inline_pow(); - void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); + Node* finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); bool inline_min_max(vmIntrinsics::ID id); Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); // This returns Type::AnyPtr, RawPtr, or OopPtr. @@ -1686,7 +1686,7 @@ return true; } -void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) { +Node* LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) { //------------------- //result=(result.isNaN())? funcAddr():result; // Check: If isNaN() by checking result!=result? then either trap @@ -1702,7 +1702,7 @@ uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_make_not_entrant); } - set_result(result); + return result; } else { // If this inlining ever returned NaN in the past, we compile a call // to the runtime to properly handle corner cases @@ -1732,9 +1732,10 @@ result_region->init_req(2, control()); result_val->init_req(2, value); - set_result(result_region, result_val); + set_control(_gvn.transform(result_region)); + return result_val; } else { - set_result(result); + return result; } } } @@ -1746,7 +1747,8 @@ Node* arg = round_double_node(argument(0)); Node* n = _gvn.transform(new (C) ExpDNode(C, control(), arg)); - finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); + n = finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); + set_result(n); C->set_has_split_ifs(true); // Has chance for split-if optimization return true; @@ -1756,27 +1758,48 @@ // Inline power instructions, if possible. bool LibraryCallKit::inline_pow() { // Pseudocode for pow - // if (x <= 0.0) { - // long longy = (long)y; - // if ((double)longy == y) { // if y is long - // if (y + 1 == y) longy = 0; // huge number: even - // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y); + // if (y == 2) { + // return x * x; + // } else { + // if (x <= 0.0) { + // long longy = (long)y; + // if ((double)longy == y) { // if y is long + // if (y + 1 == y) longy = 0; // huge number: even + // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y); + // } else { + // result = NaN; + // } // } else { - // result = NaN; + // result = DPow(x,y); // } - // } else { - // result = DPow(x,y); + // if (result != result)? { + // result = uncommon_trap() or runtime_call(); + // } + // return result; // } - // if (result != result)? { - // result = uncommon_trap() or runtime_call(); - // } - // return result; Node* x = round_double_node(argument(0)); Node* y = round_double_node(argument(2)); Node* result = NULL; + Node* const_two_node = makecon(TypeD::make(2.0)); + Node* cmp_node = _gvn.transform(new (C) CmpDNode(y, const_two_node)); + Node* bool_node = _gvn.transform(new (C) BoolNode(cmp_node, BoolTest::eq)); + IfNode* if_node = create_and_xform_if(control(), bool_node, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); + Node* if_true = _gvn.transform(new (C) IfTrueNode(if_node)); + Node* if_false = _gvn.transform(new (C) IfFalseNode(if_node)); + + RegionNode* region_node = new (C) RegionNode(3); + region_node->init_req(1, if_true); + + Node* phi_node = new (C) PhiNode(region_node, Type::DOUBLE); + // special case for x^y where y == 2, we can convert it to x * x + phi_node->init_req(1, _gvn.transform(new (C) MulDNode(x, x))); + + // set control to if_false since we will now process the false branch + set_control(if_false); + if (!too_many_traps(Deoptimization::Reason_intrinsic)) { // Short form: skip the fancy tests and just check for NaN result. result = _gvn.transform(new (C) PowDNode(C, control(), x, y)); @@ -1900,7 +1923,15 @@ result = _gvn.transform(phi); } - finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); + result = finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); + + // control from finish_pow_exp is now input to the region node + region_node->set_req(2, control()); + // the result from finish_pow_exp is now input to the phi node + phi_node->init_req(2, _gvn.transform(result)); + set_control(_gvn.transform(region_node)); + record_for_igvn(region_node); + set_result(_gvn.transform(phi_node)); C->set_has_split_ifs(true); // Has chance for split-if optimization return true; diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Apr 25 14:29:47 2014 -0400 @@ -878,7 +878,7 @@ nonstatic_field(nmethod, _entry_point, address) \ nonstatic_field(nmethod, _verified_entry_point, address) \ nonstatic_field(nmethod, _osr_entry_point, address) \ - nonstatic_field(nmethod, _lock_count, jint) \ + volatile_nonstatic_field(nmethod, _lock_count, jint) \ nonstatic_field(nmethod, _stack_traversal_mark, long) \ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, int) \ diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/test/compiler/profiling/TestMethodHandleInvokesIntrinsic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/profiling/TestMethodHandleInvokesIntrinsic.java Fri Apr 25 14:29:47 2014 -0400 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, 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 8041458 + * @summary profiling of arguments in C1 at MethodHandle invoke of intrinsic tries to profile popped argument. + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TieredStopAtLevel=3 TestMethodHandleInvokesIntrinsic + * + */ + +import java.lang.invoke.*; + +public class TestMethodHandleInvokesIntrinsic { + + static final MethodHandle mh_nanoTime; + static final MethodHandle mh_getClass; + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(long.class); + MethodHandle MH = null; + try { + MH = lookup.findStatic(System.class, "nanoTime", mt); + } catch(NoSuchMethodException nsme) { + nsme.printStackTrace(); + throw new RuntimeException("TEST FAILED", nsme); + } catch(IllegalAccessException iae) { + iae.printStackTrace(); + throw new RuntimeException("TEST FAILED", iae); + } + mh_nanoTime = MH; + + mt = MethodType.methodType(Class.class); + MH = null; + try { + MH = lookup.findVirtual(Object.class, "getClass", mt); + } catch(NoSuchMethodException nsme) { + nsme.printStackTrace(); + throw new RuntimeException("TEST FAILED", nsme); + } catch(IllegalAccessException iae) { + iae.printStackTrace(); + throw new RuntimeException("TEST FAILED", iae); + } + mh_getClass = MH; + } + + static long m1() throws Throwable { + return (long)mh_nanoTime.invokeExact(); + } + + static Class m2(Object o) throws Throwable { + return (Class)mh_getClass.invokeExact(o); + } + + static public void main(String[] args) { + try { + for (int i = 0; i < 20000; i++) { + m1(); + } + TestMethodHandleInvokesIntrinsic o = new TestMethodHandleInvokesIntrinsic(); + for (int i = 0; i < 20000; i++) { + m2(o); + } + } catch(Throwable t) { + System.out.println("Unexpected exception"); + t.printStackTrace(); + throw new RuntimeException("TEST FAILED", t); + } + + System.out.println("TEST PASSED"); + } +} diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java --- a/hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java Fri Apr 25 14:29:47 2014 -0400 @@ -66,15 +66,6 @@ public class Agent implements ClassFileTransformer { - static class MemoryChunk { - MemoryChunk other; - long[] array; - MemoryChunk(MemoryChunk other) { - other = other; - array = new long[1024 * 1024 * 1024]; - } - } - static public boolean m2(A a) { boolean res = false; if (a.getClass() == B.class) { diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java --- a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Fri Apr 25 14:29:47 2014 -0400 @@ -30,7 +30,7 @@ * @build Agent * @run main ClassFileInstaller Agent * @run main Launcher - * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent */ public class Launcher { public static void main(String[] args) throws Exception { diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Fri Apr 25 14:29:47 2014 -0400 @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs with rtm support * when rtm locking is supported by VM. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMDeoptOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions diff -r 47f5725e0d7c -r 1cad13fb2969 hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Fri Apr 25 15:50:13 2014 +0200 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Fri Apr 25 14:29:47 2014 -0400 @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs without rtm support * or on VMs without rtm locking support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMDeoptOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions