changeset 2629:b3a485ccfe86

Merge
author trims
date Thu, 23 Jun 2011 22:43:22 -0700
parents 5bb91b0db2c9 (current diff) 393e144bb99b (diff)
children e9b51b4bdcc7
files
diffstat 11 files changed, 239 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Jun 22 12:40:50 2011 -0700
+++ b/.hgtags	Thu Jun 23 22:43:22 2011 -0700
@@ -179,3 +179,4 @@
 82a81d5c5700a69333e12532bf0c4d33e885c7fc jdk7-b145
 82a81d5c5700a69333e12532bf0c4d33e885c7fc hs21-b15
 38fa55e5e79232d48f1bb8cf27d88bc094c9375a jdk7-b146
+38fa55e5e79232d48f1bb8cf27d88bc094c9375a hs21-b16
--- a/src/cpu/x86/vm/assembler_x86.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -3804,6 +3804,14 @@
   emit_arith(0x03, 0xC0, dst, src);
 }
 
+void Assembler::andq(Address dst, int32_t imm32) {
+  InstructionMark im(this);
+  prefixq(dst);
+  emit_byte(0x81);
+  emit_operand(rsp, dst, 4);
+  emit_long(imm32);
+}
+
 void Assembler::andq(Register dst, int32_t imm32) {
   (void) prefixq_and_encode(dst->encoding());
   emit_arith(0x81, 0xE0, dst, imm32);
--- a/src/cpu/x86/vm/assembler_x86.hpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Thu Jun 23 22:43:22 2011 -0700
@@ -779,6 +779,7 @@
   void andl(Register dst, Address src);
   void andl(Register dst, Register src);
 
+  void andq(Address  dst, int32_t imm32);
   void andq(Register dst, int32_t imm32);
   void andq(Register dst, Address src);
   void andq(Register dst, Register src);
--- a/src/cpu/x86/vm/x86_64.ad	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Thu Jun 23 22:43:22 2011 -0700
@@ -830,6 +830,17 @@
   }
 }
 
+// This could be in MacroAssembler but it's fairly C2 specific
+void emit_cmpfp_fixup(MacroAssembler& _masm) {
+  Label exit;
+  __ jccb(Assembler::noParity, exit);
+  __ pushf();
+  __ andq(Address(rsp, 0), 0xffffff2b);
+  __ popf();
+  __ bind(exit);
+  __ nop(); // (target for branch to avoid branch to branch)
+}
+
 
 //=============================================================================
 const bool Matcher::constant_table_absolute_addressing = true;
@@ -2173,27 +2184,9 @@
     emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
   %}
 
-  enc_class cmpfp_fixup()
-  %{
-    // jnp,s exit
-    emit_opcode(cbuf, 0x7B);
-    emit_d8(cbuf, 0x0A);
-
-    // pushfq
-    emit_opcode(cbuf, 0x9C);
-
-    // andq $0xffffff2b, (%rsp)
-    emit_opcode(cbuf, Assembler::REX_W);
-    emit_opcode(cbuf, 0x81);
-    emit_opcode(cbuf, 0x24);
-    emit_opcode(cbuf, 0x24);
-    emit_d32(cbuf, 0xffffff2b);
-
-    // popfq
-    emit_opcode(cbuf, 0x9D);
-
-    // nop (target for branch to avoid branch to branch)
-    emit_opcode(cbuf, 0x90);
+  enc_class cmpfp_fixup() %{
+      MacroAssembler _masm(&cbuf);
+      emit_cmpfp_fixup(_masm);
   %}
 
   enc_class cmpfp3(rRegI dst)
@@ -10253,14 +10246,8 @@
             "popfq\n"
     "exit:   nop\t# avoid branch to branch" %}
   ins_encode %{
-    Label L_exit;
     __ ucomiss($src$$XMMRegister, $constantaddress($con));
-    __ jcc(Assembler::noParity, L_exit);
-    __ pushf();
-    __ andq(rsp, 0xffffff2b);
-    __ popf();
-    __ bind(L_exit);
-    __ nop();
+    emit_cmpfp_fixup(_masm);
   %}
   ins_pipe(pipe_slow);
 %}
@@ -10341,14 +10328,8 @@
             "popfq\n"
     "exit:   nop\t# avoid branch to branch" %}
   ins_encode %{
-    Label L_exit;
     __ ucomisd($src$$XMMRegister, $constantaddress($con));
-    __ jcc(Assembler::noParity, L_exit);
-    __ pushf();
-    __ andq(rsp, 0xffffff2b);
-    __ popf();
-    __ bind(L_exit);
-    __ nop();
+    emit_cmpfp_fixup(_masm);
   %}
   ins_pipe(pipe_slow);
 %}
--- a/src/share/vm/code/nmethod.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/code/nmethod.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -1832,7 +1832,9 @@
   if (!method()->is_native()) {
     SimpleScopeDesc ssd(this, fr.pc());
     Bytecode_invoke call(ssd.method(), ssd.bci());
-    bool has_receiver = call.has_receiver();
+    // compiled invokedynamic call sites have an implicit receiver at
+    // resolution time, so make sure it gets GC'ed.
+    bool has_receiver = !call.is_invokestatic();
     Symbol* signature = call.signature();
     fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
   }
--- a/src/share/vm/opto/bytecodeInfo.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -35,14 +35,16 @@
 
 //=============================================================================
 //------------------------------InlineTree-------------------------------------
-InlineTree::InlineTree( Compile* c,
-                        const InlineTree *caller_tree, ciMethod* callee,
-                        JVMState* caller_jvms, int caller_bci,
-                        float site_invoke_ratio, int site_depth_adjust)
-: C(c), _caller_jvms(caller_jvms),
-  _caller_tree((InlineTree*)caller_tree),
-  _method(callee), _site_invoke_ratio(site_invoke_ratio),
-  _site_depth_adjust(site_depth_adjust),
+InlineTree::InlineTree(Compile* c,
+                       const InlineTree *caller_tree, ciMethod* callee,
+                       JVMState* caller_jvms, int caller_bci,
+                       float site_invoke_ratio, int max_inline_level) :
+  C(c),
+  _caller_jvms(caller_jvms),
+  _caller_tree((InlineTree*) caller_tree),
+  _method(callee),
+  _site_invoke_ratio(site_invoke_ratio),
+  _max_inline_level(max_inline_level),
   _count_inline_bcs(method()->code_size())
 {
   NOT_PRODUCT(_count_inlines = 0;)
@@ -66,10 +68,13 @@
 }
 
 InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms,
-                       float site_invoke_ratio, int site_depth_adjust)
-: C(c), _caller_jvms(caller_jvms), _caller_tree(NULL),
-  _method(callee_method), _site_invoke_ratio(site_invoke_ratio),
-  _site_depth_adjust(site_depth_adjust),
+                       float site_invoke_ratio, int max_inline_level) :
+  C(c),
+  _caller_jvms(caller_jvms),
+  _caller_tree(NULL),
+  _method(callee_method),
+  _site_invoke_ratio(site_invoke_ratio),
+  _max_inline_level(max_inline_level),
   _count_inline_bcs(method()->code_size())
 {
   NOT_PRODUCT(_count_inlines = 0;)
@@ -94,7 +99,7 @@
   if(callee_method->should_inline()) {
     *wci_result = *(WarmCallInfo::always_hot());
     if (PrintInlining && Verbose) {
-      CompileTask::print_inline_indent(inline_depth());
+      CompileTask::print_inline_indent(inline_level());
       tty->print_cr("Inlined method is hot: ");
     }
     return NULL;
@@ -109,7 +114,7 @@
      size < InlineThrowMaxSize ) {
     wci_result->set_profit(wci_result->profit() * 100);
     if (PrintInlining && Verbose) {
-      CompileTask::print_inline_indent(inline_depth());
+      CompileTask::print_inline_indent(inline_level());
       tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
     }
     return NULL;
@@ -149,9 +154,9 @@
 
     max_inline_size = C->freq_inline_size();
     if (size <= max_inline_size && TraceFrequencyInlining) {
-      CompileTask::print_inline_indent(inline_depth());
+      CompileTask::print_inline_indent(inline_level());
       tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count);
-      CompileTask::print_inline_indent(inline_depth());
+      CompileTask::print_inline_indent(inline_level());
       callee_method->print();
       tty->cr();
     }
@@ -322,7 +327,7 @@
   if (!C->do_inlining() && InlineAccessors) {
     return "not an accessor";
   }
-  if( inline_depth() > MaxInlineLevel ) {
+  if (inline_level() > _max_inline_level) {
     return "inlining too deep";
   }
 
@@ -392,7 +397,7 @@
 //------------------------------print_inlining---------------------------------
 // Really, the failure_msg can be a success message also.
 void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
-  CompileTask::print_inlining(callee_method, inline_depth(), caller_bci, failure_msg ? failure_msg : "inline");
+  CompileTask::print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline");
   if (callee_method == NULL)  tty->print(" callee not monotonic or profiled");
   if (Verbose && callee_method) {
     const InlineTree *top = this;
@@ -500,25 +505,25 @@
   if (old_ilt != NULL) {
     return old_ilt;
   }
-  int new_depth_adjust = 0;
+  int max_inline_level_adjust = 0;
   if (caller_jvms->method() != NULL) {
     if (caller_jvms->method()->is_method_handle_adapter())
-      new_depth_adjust -= 1;  // don't count actions in MH or indy adapter frames
+      max_inline_level_adjust += 1;  // don't count actions in MH or indy adapter frames
     else if (callee_method->is_method_handle_invoke()) {
-      new_depth_adjust -= 1;  // don't count method handle calls from java.lang.invoke implem
+      max_inline_level_adjust += 1;  // don't count method handle calls from java.lang.invoke implem
     }
-    if (new_depth_adjust != 0 && PrintInlining) {
-      CompileTask::print_inline_indent(inline_depth());
+    if (max_inline_level_adjust != 0 && PrintInlining && (Verbose || WizardMode)) {
+      CompileTask::print_inline_indent(inline_level());
       tty->print_cr(" \\-> discounting inline depth");
     }
-    if (new_depth_adjust != 0 && C->log()) {
+    if (max_inline_level_adjust != 0 && C->log()) {
       int id1 = C->log()->identify(caller_jvms->method());
       int id2 = C->log()->identify(callee_method);
-      C->log()->elem("inline_depth_discount caller='%d' callee='%d'", id1, id2);
+      C->log()->elem("inline_level_discount caller='%d' callee='%d'", id1, id2);
     }
   }
-  InlineTree *ilt = new InlineTree(C, this, callee_method, caller_jvms, caller_bci, recur_frequency, _site_depth_adjust + new_depth_adjust);
-  _subtrees.append( ilt );
+  InlineTree* ilt = new InlineTree(C, this, callee_method, caller_jvms, caller_bci, recur_frequency, _max_inline_level + max_inline_level_adjust);
+  _subtrees.append(ilt);
 
   NOT_PRODUCT( _count_inlines += 1; )
 
@@ -543,7 +548,7 @@
   Compile* C = Compile::current();
 
   // Root of inline tree
-  InlineTree *ilt = new InlineTree(C, NULL, C->method(), NULL, -1, 1.0F, 0);
+  InlineTree* ilt = new InlineTree(C, NULL, C->method(), NULL, -1, 1.0F, MaxInlineLevel);
 
   return ilt;
 }
--- a/src/share/vm/opto/doCall.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/opto/doCall.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -183,7 +183,7 @@
         // TO DO:  When UseOldInlining is removed, copy the ILT code elsewhere.
         float site_invoke_ratio = prof_factor;
         // Note:  ilt is for the root of this parse, not the present call site.
-        ilt = new InlineTree(this, jvms->method(), jvms->caller(), site_invoke_ratio, 0);
+        ilt = new InlineTree(this, jvms->method(), jvms->caller(), site_invoke_ratio, MaxInlineLevel);
       }
       WarmCallInfo scratch_ci;
       if (!UseOldInlining)
--- a/src/share/vm/opto/loopTransform.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/opto/loopTransform.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -83,7 +83,7 @@
 #ifdef ASSERT
   BoolTest::mask bt = cl->loopexit()->test_trip();
   assert(bt == BoolTest::lt || bt == BoolTest::gt ||
-         (bt == BoolTest::ne && !LoopLimitCheck), "canonical test is expected");
+         bt == BoolTest::ne, "canonical test is expected");
 #endif
 
   Node* init_n = cl->init_trip();
@@ -1070,9 +1070,11 @@
   // direction:
   // positive stride use <
   // negative stride use >
+  //
+  // not-equal test is kept for post loop to handle case
+  // when init > limit when stride > 0 (and reverse).
 
   if (pre_end->in(CountedLoopEndNode::TestValue)->as_Bool()->_test._test == BoolTest::ne) {
-    assert(!LoopLimitCheck, "only canonical tests (lt or gt) are expected");
 
     BoolTest::mask new_test = (main_end->stride_con() > 0) ? BoolTest::lt : BoolTest::gt;
     // Modify pre loop end condition
--- a/src/share/vm/opto/loopnode.cpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/opto/loopnode.cpp	Thu Jun 23 22:43:22 2011 -0700
@@ -453,7 +453,12 @@
   // Now we need to canonicalize loop condition.
   if (bt == BoolTest::ne) {
     assert(stride_con == 1 || stride_con == -1, "simple increment only");
-    bt = (stride_con > 0) ? BoolTest::lt : BoolTest::gt;
+    // 'ne' can be replaced with 'lt' only when init < limit.
+    if (stride_con > 0 && init_t->_hi < limit_t->_lo)
+      bt = BoolTest::lt;
+    // 'ne' can be replaced with 'gt' only when init > limit.
+    if (stride_con < 0 && init_t->_lo > limit_t->_hi)
+      bt = BoolTest::gt;
   }
 
   if (incl_limit) {
--- a/src/share/vm/opto/parse.hpp	Wed Jun 22 12:40:50 2011 -0700
+++ b/src/share/vm/opto/parse.hpp	Thu Jun 23 22:43:22 2011 -0700
@@ -50,7 +50,7 @@
   // Always between 0.0 and 1.0.  Represents the percentage of the method's
   // total execution time used at this call site.
   const float _site_invoke_ratio;
-  const int   _site_depth_adjust;
+  const int   _max_inline_level;  // the maximum inline level for this sub-tree (may be adjusted)
   float compute_callee_frequency( int caller_bci ) const;
 
   GrowableArray<InlineTree*> _subtrees;
@@ -63,7 +63,7 @@
              JVMState* caller_jvms,
              int caller_bci,
              float site_invoke_ratio,
-             int site_depth_adjust);
+             int max_inline_level);
   InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
                                            JVMState* caller_jvms,
                                            int caller_bci);
@@ -74,7 +74,7 @@
 
   InlineTree *caller_tree()       const { return _caller_tree;  }
   InlineTree* callee_at(int bci, ciMethod* m) const;
-  int         inline_depth()      const { return stack_depth() + _site_depth_adjust; }
+  int         inline_level()      const { return stack_depth(); }
   int         stack_depth()       const { return _caller_jvms ? _caller_jvms->depth() : 0; }
 
 public:
@@ -82,7 +82,7 @@
   static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false);
 
   // For temporary (stack-allocated, stateless) ilts:
-  InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int site_depth_adjust);
+  InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level);
 
   // InlineTree enum
   enum InlineStyle {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/7052494/Test7052494.java	Thu Jun 23 22:43:22 2011 -0700
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2011, 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 7052494
+ * @summary Eclipse test fails on JDK 7 b142
+ *
+ * @run main/othervm -Xbatch Test7052494
+ */
+
+
+public class Test7052494 {
+
+  static int test1(int i, int limit) {
+    int result = 0;
+    while (i++ != 0) {
+      if (result >= limit)
+        break;
+      result = i*2;
+    }
+    return result;
+  }
+
+  static int test2(int i, int limit) {
+    int result = 0;
+    while (i-- != 0) {
+      if (result <= limit)
+        break;
+      result = i*2;
+    }
+    return result;
+  }
+
+  static void test3(int i, int limit, int arr[]) {
+    while (i++ != 0) {
+      if (arr[i-1] >= limit)
+        break;
+      arr[i] = i*2;
+    }
+  }
+
+  static void test4(int i, int limit, int arr[]) {
+    while (i-- != 0) {
+      if (arr[arr.length + i + 1] <= limit)
+        break;
+      arr[arr.length + i] = i*2;
+    }
+  }
+
+  // Empty loop rolls through MAXINT if i > 0
+  static int test5(int i) {
+    int result = 0;
+    while (i++ != 0) {
+      result = i*2;
+    }
+    return result;
+  }
+
+  // Empty loop rolls through MININT if i < 0
+  static int test6(int i) {
+    int result = 0;
+    while (i-- != 0) {
+      result = i*2;
+    }
+    return result;
+  }
+
+  public static void main(String [] args) {
+    boolean failed = false;
+    int[] arr = new int[8];
+    int[] ar3 = { 0, 0, 4, 6, 8, 10, 0, 0 };
+    int[] ar4 = { 0, 0, 0, -10, -8, -6, -4, 0 };
+    for (int i = 0; i < 11000; i++) {
+      int k = test1(1, 10);
+      if (k != 10) {
+        System.out.println("FAILED: " + k + " != 10");
+        failed = true;
+        break;
+      }
+    }
+    for (int i = 0; i < 11000; i++) {
+      int k = test2(-1, -10);
+      if (k != -10) {
+        System.out.println("FAILED: " + k + " != -10");
+        failed = true;
+        break;
+      }
+    }
+    for (int i = 0; i < 11000; i++) {
+      java.util.Arrays.fill(arr, 0);
+      test3(1, 10, arr);
+      if (!java.util.Arrays.equals(arr,ar3)) {
+        System.out.println("FAILED: arr = { " + arr[0] + ", "
+                                              + arr[1] + ", "
+                                              + arr[2] + ", "
+                                              + arr[3] + ", "
+                                              + arr[4] + ", "
+                                              + arr[5] + ", "
+                                              + arr[6] + ", "
+                                              + arr[7] + " }");
+        failed = true;
+        break;
+      }
+    }
+    for (int i = 0; i < 11000; i++) {
+      java.util.Arrays.fill(arr, 0);
+      test4(-1, -10, arr);
+      if (!java.util.Arrays.equals(arr,ar4)) {
+        System.out.println("FAILED: arr = { " + arr[0] + ", "
+                                              + arr[1] + ", "
+                                              + arr[2] + ", "
+                                              + arr[3] + ", "
+                                              + arr[4] + ", "
+                                              + arr[5] + ", "
+                                              + arr[6] + ", "
+                                              + arr[7] + " }");
+        failed = true;
+        break;
+      }
+    }
+    for (int i = 0; i < 11000; i++) {
+      int k = test5(1);
+      if (k != 0) {
+        System.out.println("FAILED: " + k + " != 0");
+        failed = true;
+        break;
+      }
+    }
+    for (int i = 0; i < 11000; i++) {
+      int k = test6(-1);
+      if (k != 0) {
+        System.out.println("FAILED: " + k + " != 0");
+        failed = true;
+        break;
+      }
+    }
+    if (failed)
+      System.exit(97);
+  }
+}