Mon, 15 Jul 2013 06:27:46 -0700
Merge
1.1 --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Jul 12 17:08:52 2013 -0700 1.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Mon Jul 15 06:27:46 2013 -0700 1.3 @@ -138,6 +138,16 @@ 1.4 return false; 1.5 } 1.6 1.7 +// return true if all argument elements of vars are returned 1.8 +bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) { 1.9 + for (int i = 0; i < _arg_size; i++) { 1.10 + if (vars.contains(i) && !_arg_returned.test(i)) { 1.11 + return false; 1.12 + } 1.13 + } 1.14 + return true; 1.15 +} 1.16 + 1.17 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) { 1.18 for (int i = 0; i < _arg_size; i++) { 1.19 if (vars.contains(i)) { 1.20 @@ -166,6 +176,11 @@ 1.21 if (vars.contains_unknown() || vars.contains_vars()) { 1.22 _return_allocated = false; 1.23 } 1.24 + if (_return_local && vars.contains_vars() && !returns_all(vars)) { 1.25 + // Return result should be invalidated if args in new 1.26 + // state are not recorded in return state. 1.27 + _return_local = false; 1.28 + } 1.29 } 1.30 } 1.31
2.1 --- a/src/share/vm/ci/bcEscapeAnalyzer.hpp Fri Jul 12 17:08:52 2013 -0700 2.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp Mon Jul 15 06:27:46 2013 -0700 2.3 @@ -80,6 +80,7 @@ 2.4 void set_returned(ArgumentMap vars); 2.5 bool is_argument(ArgumentMap vars); 2.6 bool is_arg_stack(ArgumentMap vars); 2.7 + bool returns_all(ArgumentMap vars); 2.8 void clear_bits(ArgumentMap vars, VectorSet &bs); 2.9 void set_method_escape(ArgumentMap vars); 2.10 void set_global_escape(ArgumentMap vars, bool merge = false);
3.1 --- a/src/share/vm/opto/matcher.cpp Fri Jul 12 17:08:52 2013 -0700 3.2 +++ b/src/share/vm/opto/matcher.cpp Mon Jul 15 06:27:46 2013 -0700 3.3 @@ -2305,26 +2305,26 @@ 3.4 // atomic instruction acting as a store_load barrier without any 3.5 // intervening volatile load, and thus we don't need a barrier here. 3.6 // We retain the Node to act as a compiler ordering barrier. 3.7 -bool Matcher::post_store_load_barrier(const Node *vmb) { 3.8 - Compile *C = Compile::current(); 3.9 - assert( vmb->is_MemBar(), "" ); 3.10 - assert( vmb->Opcode() != Op_MemBarAcquire, "" ); 3.11 - const MemBarNode *mem = (const MemBarNode*)vmb; 3.12 +bool Matcher::post_store_load_barrier(const Node* vmb) { 3.13 + Compile* C = Compile::current(); 3.14 + assert(vmb->is_MemBar(), ""); 3.15 + assert(vmb->Opcode() != Op_MemBarAcquire, ""); 3.16 + const MemBarNode* membar = vmb->as_MemBar(); 3.17 3.18 - // Get the Proj node, ctrl, that can be used to iterate forward 3.19 - Node *ctrl = NULL; 3.20 - DUIterator_Fast imax, i = mem->fast_outs(imax); 3.21 - while( true ) { 3.22 - ctrl = mem->fast_out(i); // Throw out-of-bounds if proj not found 3.23 - assert( ctrl->is_Proj(), "only projections here" ); 3.24 - ProjNode *proj = (ProjNode*)ctrl; 3.25 - if( proj->_con == TypeFunc::Control && 3.26 - !C->node_arena()->contains(ctrl) ) // Unmatched old-space only 3.27 + // Get the Ideal Proj node, ctrl, that can be used to iterate forward 3.28 + Node* ctrl = NULL; 3.29 + for (DUIterator_Fast imax, i = membar->fast_outs(imax); i < imax; i++) { 3.30 + Node* p = membar->fast_out(i); 3.31 + assert(p->is_Proj(), "only projections here"); 3.32 + if ((p->as_Proj()->_con == TypeFunc::Control) && 3.33 + !C->node_arena()->contains(p)) { // Unmatched old-space only 3.34 + ctrl = p; 3.35 break; 3.36 - i++; 3.37 + } 3.38 } 3.39 + assert((ctrl != NULL), "missing control projection"); 3.40 3.41 - for( DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++ ) { 3.42 + for (DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++) { 3.43 Node *x = ctrl->fast_out(j); 3.44 int xop = x->Opcode(); 3.45 3.46 @@ -2336,37 +2336,36 @@ 3.47 // that a monitor exit operation contains a serializing instruction. 3.48 3.49 if (xop == Op_MemBarVolatile || 3.50 - xop == Op_FastLock || 3.51 xop == Op_CompareAndSwapL || 3.52 xop == Op_CompareAndSwapP || 3.53 xop == Op_CompareAndSwapN || 3.54 - xop == Op_CompareAndSwapI) 3.55 + xop == Op_CompareAndSwapI) { 3.56 return true; 3.57 + } 3.58 + 3.59 + // Op_FastLock previously appeared in the Op_* list above. 3.60 + // With biased locking we're no longer guaranteed that a monitor 3.61 + // enter operation contains a serializing instruction. 3.62 + if ((xop == Op_FastLock) && !UseBiasedLocking) { 3.63 + return true; 3.64 + } 3.65 3.66 if (x->is_MemBar()) { 3.67 // We must retain this membar if there is an upcoming volatile 3.68 - // load, which will be preceded by acquire membar. 3.69 - if (xop == Op_MemBarAcquire) 3.70 + // load, which will be followed by acquire membar. 3.71 + if (xop == Op_MemBarAcquire) { 3.72 return false; 3.73 - // For other kinds of barriers, check by pretending we 3.74 - // are them, and seeing if we can be removed. 3.75 - else 3.76 - return post_store_load_barrier((const MemBarNode*)x); 3.77 + } else { 3.78 + // For other kinds of barriers, check by pretending we 3.79 + // are them, and seeing if we can be removed. 3.80 + return post_store_load_barrier(x->as_MemBar()); 3.81 + } 3.82 } 3.83 3.84 - // Delicate code to detect case of an upcoming fastlock block 3.85 - if( x->is_If() && x->req() > 1 && 3.86 - !C->node_arena()->contains(x) ) { // Unmatched old-space only 3.87 - Node *iff = x; 3.88 - Node *bol = iff->in(1); 3.89 - // The iff might be some random subclass of If or bol might be Con-Top 3.90 - if (!bol->is_Bool()) return false; 3.91 - assert( bol->req() > 1, "" ); 3.92 - return (bol->in(1)->Opcode() == Op_FastUnlock); 3.93 + // probably not necessary to check for these 3.94 + if (x->is_Call() || x->is_SafePoint() || x->is_block_proj()) { 3.95 + return false; 3.96 } 3.97 - // probably not necessary to check for these 3.98 - if (x->is_Call() || x->is_SafePoint() || x->is_block_proj()) 3.99 - return false; 3.100 } 3.101 return false; 3.102 }
4.1 --- a/src/share/vm/opto/parse3.cpp Fri Jul 12 17:08:52 2013 -0700 4.2 +++ b/src/share/vm/opto/parse3.cpp Mon Jul 15 06:27:46 2013 -0700 4.3 @@ -294,25 +294,7 @@ 4.4 // If reference is volatile, prevent following volatiles ops from 4.5 // floating up before the volatile write. 4.6 if (is_vol) { 4.7 - // First place the specific membar for THIS volatile index. This first 4.8 - // membar is dependent on the store, keeping any other membars generated 4.9 - // below from floating up past the store. 4.10 - int adr_idx = C->get_alias_index(adr_type); 4.11 - insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store); 4.12 - 4.13 - // Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed 4.14 - // volatile alias indices. Skip this if the membar is redundant. 4.15 - if (adr_idx != Compile::AliasIdxBot) { 4.16 - insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store); 4.17 - } 4.18 - 4.19 - // Finally, place alias-index-specific membars for each volatile index 4.20 - // that isn't the adr_idx membar. Typically there's only 1 or 2. 4.21 - for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) { 4.22 - if (i != adr_idx && C->alias_type(i)->is_volatile()) { 4.23 - insert_mem_bar_volatile(Op_MemBarVolatile, i, store); 4.24 - } 4.25 - } 4.26 + insert_mem_bar(Op_MemBarVolatile); // Use fat membar 4.27 } 4.28 4.29 // If the field is final, the rules of Java say we are in <init> or <clinit>.
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/compiler/EscapeAnalysis/Test8020215.java Mon Jul 15 06:27:46 2013 -0700 5.3 @@ -0,0 +1,82 @@ 5.4 +/* 5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8020215 5.30 + * @summary Different execution plan when using JIT vs interpreter 5.31 + * @run main Test8020215 5.32 + */ 5.33 + 5.34 +import java.util.ArrayList; 5.35 +import java.util.List; 5.36 + 5.37 +public class Test8020215 { 5.38 + public static class NamedObject { 5.39 + public int id; 5.40 + public String name; 5.41 + public NamedObject(int id, String name) { 5.42 + this.id = id; 5.43 + this.name = name; 5.44 + } 5.45 + } 5.46 + 5.47 + public static class NamedObjectList { 5.48 + public List<NamedObject> namedObjectList = new ArrayList<NamedObject>(); 5.49 + 5.50 + public NamedObject getBest(int id) { 5.51 + NamedObject bestObject = null; 5.52 + for (NamedObject o : namedObjectList) { 5.53 + bestObject = id==o.id ? getBetter(bestObject, o) : bestObject; 5.54 + } 5.55 + return (bestObject != null) ? bestObject : null; 5.56 + } 5.57 + 5.58 + private static NamedObject getBetter(NamedObject p1, NamedObject p2) { 5.59 + return (p1 == null) ? p2 : (p2 == null) ? p1 : (p2.name.compareTo(p1.name) >= 0) ? p2 : p1; 5.60 + } 5.61 + } 5.62 + 5.63 + static void test(NamedObjectList b, int i) { 5.64 + NamedObject x = b.getBest(2); 5.65 + // test 5.66 + if (x == null) { 5.67 + throw new RuntimeException("x should never be null here! (i=" + i + ")"); 5.68 + } 5.69 + } 5.70 + 5.71 + public static void main(String[] args) { 5.72 + // setup 5.73 + NamedObjectList b = new NamedObjectList(); 5.74 + for (int i = 0; i < 10000; i++) { 5.75 + b.namedObjectList.add(new NamedObject(1, "2012-12-31")); 5.76 + } 5.77 + b.namedObjectList.add(new NamedObject(2, "2013-12-31")); 5.78 + 5.79 + // execution 5.80 + for (int i = 0; i < 12000; i++) { 5.81 + test(b, i); 5.82 + } 5.83 + System.out.println("PASSED"); 5.84 + } 5.85 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/compiler/membars/DekkerTest.java Mon Jul 15 06:27:46 2013 -0700 6.3 @@ -0,0 +1,163 @@ 6.4 +/* 6.5 + * Copyright 2013 SAP AG. All Rights Reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/** 6.28 + * @test 6.29 + * @bug 8007898 6.30 + * @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier(). 6.31 + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest 6.32 + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest 6.33 + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest 6.34 + * @author Martin Doerr martin DOT doerr AT sap DOT com 6.35 + * 6.36 + * Run 3 times since the failure is intermittent. 6.37 + */ 6.38 + 6.39 +public class DekkerTest { 6.40 + 6.41 + /* 6.42 + Read After Write Test (basically a simple Dekker test with volatile variables) 6.43 + Derived from the original jcstress test, available at: 6.44 + http://hg.openjdk.java.net/code-tools/jcstress/file/6c339a5aa00d/ 6.45 + tests-custom/src/main/java/org/openjdk/jcstress/tests/volatiles/DekkerTest.java 6.46 + */ 6.47 + 6.48 + static final int ITERATIONS = 1000000; 6.49 + 6.50 + static class TestData { 6.51 + public volatile int a; 6.52 + public volatile int b; 6.53 + } 6.54 + 6.55 + static class ResultData { 6.56 + public int a; 6.57 + public int b; 6.58 + } 6.59 + 6.60 + TestData[] testDataArray; 6.61 + ResultData[] results; 6.62 + 6.63 + volatile boolean start; 6.64 + 6.65 + public DekkerTest() { 6.66 + testDataArray = new TestData[ITERATIONS]; 6.67 + results = new ResultData[ITERATIONS]; 6.68 + for (int i = 0; i < ITERATIONS; ++i) { 6.69 + testDataArray[i] = new TestData(); 6.70 + results[i] = new ResultData(); 6.71 + } 6.72 + start = false; 6.73 + } 6.74 + 6.75 + public void reset() { 6.76 + for (int i = 0; i < ITERATIONS; ++i) { 6.77 + testDataArray[i].a = 0; 6.78 + testDataArray[i].b = 0; 6.79 + results[i].a = 0; 6.80 + results[i].b = 0; 6.81 + } 6.82 + start = false; 6.83 + } 6.84 + 6.85 + int actor1(TestData t) { 6.86 + t.a = 1; 6.87 + return t.b; 6.88 + } 6.89 + 6.90 + int actor2(TestData t) { 6.91 + t.b = 1; 6.92 + return t.a; 6.93 + } 6.94 + 6.95 + class Runner1 extends Thread { 6.96 + public void run() { 6.97 + do {} while (!start); 6.98 + for (int i = 0; i < ITERATIONS; ++i) { 6.99 + results[i].a = actor1(testDataArray[i]); 6.100 + } 6.101 + } 6.102 + } 6.103 + 6.104 + class Runner2 extends Thread { 6.105 + public void run() { 6.106 + do {} while (!start); 6.107 + for (int i = 0; i < ITERATIONS; ++i) { 6.108 + results[i].b = actor2(testDataArray[i]); 6.109 + } 6.110 + } 6.111 + } 6.112 + 6.113 + void testRunner() { 6.114 + Thread thread1 = new Runner1(); 6.115 + Thread thread2 = new Runner2(); 6.116 + thread1.start(); 6.117 + thread2.start(); 6.118 + do {} while (!thread1.isAlive()); 6.119 + do {} while (!thread2.isAlive()); 6.120 + start = true; 6.121 + Thread.yield(); 6.122 + try { 6.123 + thread1.join(); 6.124 + thread2.join(); 6.125 + } catch (InterruptedException e) { 6.126 + System.out.println("interrupted!"); 6.127 + System.exit(1); 6.128 + } 6.129 + } 6.130 + 6.131 + boolean printResult() { 6.132 + int[] count = new int[4]; 6.133 + for (int i = 0; i < ITERATIONS; ++i) { 6.134 + int event_kind = (results[i].a << 1) + results[i].b; 6.135 + ++count[event_kind]; 6.136 + } 6.137 + if (count[0] == 0 && count[3] == 0) { 6.138 + System.out.println("[not interesting]"); 6.139 + return false; // not interesting 6.140 + } 6.141 + String error = (count[0] == 0) ? " ok" : " disallowed!"; 6.142 + System.out.println("[0,0] " + count[0] + error); 6.143 + System.out.println("[0,1] " + count[1]); 6.144 + System.out.println("[1,0] " + count[2]); 6.145 + System.out.println("[1,1] " + count[3]); 6.146 + return (count[0] != 0); 6.147 + } 6.148 + 6.149 + public static void main(String args[]) { 6.150 + DekkerTest test = new DekkerTest(); 6.151 + final int runs = 30; 6.152 + int failed = 0; 6.153 + for (int c = 0; c < runs; ++c) { 6.154 + test.testRunner(); 6.155 + if (test.printResult()) { 6.156 + failed++; 6.157 + } 6.158 + test.reset(); 6.159 + } 6.160 + if (failed > 0) { 6.161 + throw new InternalError("FAILED. Got " + failed + " failed ITERATIONS"); 6.162 + } 6.163 + System.out.println("PASSED."); 6.164 + } 6.165 + 6.166 +}