Mercurial > hg > truffle
annotate src/share/vm/opto/loopUnswitch.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 2aff40cb4703 |
children | 9e69e8d1c900 |
rev | line source |
---|---|
0 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6804
diff
changeset
|
2 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "opto/connode.hpp" | |
28 #include "opto/loopnode.hpp" | |
29 #include "opto/rootnode.hpp" | |
0 | 30 |
31 //================= Loop Unswitching ===================== | |
32 // | |
33 // orig: transformed: | |
34 // if (invariant-test) then | |
2445 | 35 // predicate predicate |
0 | 36 // loop loop |
37 // stmt1 stmt1 | |
38 // if (invariant-test) then stmt2 | |
39 // stmt2 stmt4 | |
40 // else endloop | |
41 // stmt3 else | |
2445 | 42 // endif predicate [clone] |
43 // stmt4 loop [clone] | |
44 // endloop stmt1 [clone] | |
45 // stmt3 | |
0 | 46 // stmt4 [clone] |
47 // endloop | |
48 // endif | |
49 // | |
50 // Note: the "else" clause may be empty | |
51 | |
52 //------------------------------policy_unswitching----------------------------- | |
53 // Return TRUE or FALSE if the loop should be unswitched | |
54 // (ie. clone loop with an invariant test that does not exit the loop) | |
55 bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { | |
56 if( !LoopUnswitching ) { | |
57 return false; | |
58 } | |
108 | 59 if (!_head->is_Loop()) { |
60 return false; | |
61 } | |
7196
2aff40cb4703
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
6842
diff
changeset
|
62 uint nodes_left = MaxNodeLimit - phase->C->live_nodes(); |
0 | 63 if (2 * _body.size() > nodes_left) { |
64 return false; // Too speculative if running low on nodes. | |
65 } | |
66 LoopNode* head = _head->as_Loop(); | |
67 if (head->unswitch_count() + 1 > head->unswitch_max()) { | |
68 return false; | |
69 } | |
70 return phase->find_unswitching_candidate(this) != NULL; | |
71 } | |
72 | |
73 //------------------------------find_unswitching_candidate----------------------------- | |
74 // Find candidate "if" for unswitching | |
75 IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const { | |
76 | |
77 // Find first invariant test that doesn't exit the loop | |
78 LoopNode *head = loop->_head->as_Loop(); | |
79 IfNode* unswitch_iff = NULL; | |
80 Node* n = head->in(LoopNode::LoopBackControl); | |
81 while (n != head) { | |
82 Node* n_dom = idom(n); | |
83 if (n->is_Region()) { | |
84 if (n_dom->is_If()) { | |
85 IfNode* iff = n_dom->as_If(); | |
86 if (iff->in(1)->is_Bool()) { | |
87 BoolNode* bol = iff->in(1)->as_Bool(); | |
88 if (bol->in(1)->is_Cmp()) { | |
89 // If condition is invariant and not a loop exit, | |
90 // then found reason to unswitch. | |
91 if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) { | |
92 unswitch_iff = iff; | |
93 } | |
94 } | |
95 } | |
96 } | |
97 } | |
98 n = n_dom; | |
99 } | |
100 return unswitch_iff; | |
101 } | |
102 | |
103 //------------------------------do_unswitching----------------------------- | |
104 // Clone loop with an invariant test (that does not exit) and | |
105 // insert a clone of the test that selects which version to | |
106 // execute. | |
107 void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { | |
108 | |
109 // Find first invariant test that doesn't exit the loop | |
110 LoopNode *head = loop->_head->as_Loop(); | |
111 | |
112 IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop); | |
113 assert(unswitch_iff != NULL, "should be at least one"); | |
114 | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
115 #ifndef PRODUCT |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
116 if (TraceLoopOpts) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
117 tty->print("Unswitch %d ", head->unswitch_count()+1); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
118 loop->dump_head(); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
119 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
120 #endif |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
121 |
0 | 122 // Need to revert back to normal loop |
123 if (head->is_CountedLoop() && !head->as_CountedLoop()->is_normal_loop()) { | |
124 head->as_CountedLoop()->set_normal_loop(); | |
125 } | |
126 | |
127 ProjNode* proj_true = create_slow_version_of_loop(loop, old_new); | |
128 | |
2445 | 129 #ifdef ASSERT |
130 Node* uniqc = proj_true->unique_ctrl_out(); | |
131 Node* entry = head->in(LoopNode::EntryControl); | |
132 Node* predicate = find_predicate(entry); | |
3345 | 133 if (predicate != NULL && LoopLimitCheck && UseLoopPredicate) { |
134 // We may have two predicates, find first. | |
135 entry = find_predicate(entry->in(0)->in(0)); | |
136 if (entry != NULL) predicate = entry; | |
137 } | |
2445 | 138 if (predicate != NULL) predicate = predicate->in(0); |
139 assert(proj_true->is_IfTrue() && | |
140 (predicate == NULL && uniqc == head || | |
141 predicate != NULL && uniqc == predicate), "by construction"); | |
142 #endif | |
0 | 143 // Increment unswitch count |
144 LoopNode* head_clone = old_new[head->_idx]->as_Loop(); | |
145 int nct = head->unswitch_count() + 1; | |
146 head->set_unswitch_count(nct); | |
147 head_clone->set_unswitch_count(nct); | |
148 | |
149 // Add test to new "if" outside of loop | |
150 IfNode* invar_iff = proj_true->in(0)->as_If(); | |
151 Node* invar_iff_c = invar_iff->in(0); | |
152 BoolNode* bol = unswitch_iff->in(1)->as_Bool(); | |
153 invar_iff->set_req(1, bol); | |
154 invar_iff->_prob = unswitch_iff->_prob; | |
155 | |
156 ProjNode* proj_false = invar_iff->proj_out(0)->as_Proj(); | |
157 | |
605 | 158 // Hoist invariant casts out of each loop to the appropriate |
0 | 159 // control projection. |
160 | |
161 Node_List worklist; | |
162 | |
163 for (DUIterator_Fast imax, i = unswitch_iff->fast_outs(imax); i < imax; i++) { | |
164 ProjNode* proj= unswitch_iff->fast_out(i)->as_Proj(); | |
165 // Copy to a worklist for easier manipulation | |
166 for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) { | |
167 Node* use = proj->fast_out(j); | |
168 if (use->Opcode() == Op_CheckCastPP && loop->is_invariant(use->in(1))) { | |
169 worklist.push(use); | |
170 } | |
171 } | |
172 ProjNode* invar_proj = invar_iff->proj_out(proj->_con)->as_Proj(); | |
173 while (worklist.size() > 0) { | |
174 Node* use = worklist.pop(); | |
175 Node* nuse = use->clone(); | |
176 nuse->set_req(0, invar_proj); | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
177 _igvn.replace_input_of(use, 1, nuse); |
0 | 178 register_new_node(nuse, invar_proj); |
179 // Same for the clone | |
180 Node* use_clone = old_new[use->_idx]; | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
181 _igvn.replace_input_of(use_clone, 1, nuse); |
0 | 182 } |
183 } | |
184 | |
185 // Hardwire the control paths in the loops into if(true) and if(false) | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
186 _igvn.rehash_node_delayed(unswitch_iff); |
0 | 187 short_circuit_if(unswitch_iff, proj_true); |
188 | |
189 IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If(); | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
190 _igvn.rehash_node_delayed(unswitch_iff_clone); |
0 | 191 short_circuit_if(unswitch_iff_clone, proj_false); |
192 | |
193 // Reoptimize loops | |
194 loop->record_for_igvn(); | |
195 for(int i = loop->_body.size() - 1; i >= 0 ; i--) { | |
196 Node *n = loop->_body[i]; | |
197 Node *n_clone = old_new[n->_idx]; | |
198 _igvn._worklist.push(n_clone); | |
199 } | |
200 | |
201 #ifndef PRODUCT | |
202 if (TraceLoopUnswitching) { | |
203 tty->print_cr("Loop unswitching orig: %d @ %d new: %d @ %d", | |
204 head->_idx, unswitch_iff->_idx, | |
205 old_new[head->_idx]->_idx, unswitch_iff_clone->_idx); | |
206 } | |
207 #endif | |
208 | |
209 C->set_major_progress(); | |
210 } | |
211 | |
212 //-------------------------create_slow_version_of_loop------------------------ | |
213 // Create a slow version of the loop by cloning the loop | |
214 // and inserting an if to select fast-slow versions. | |
215 // Return control projection of the entry to the fast version. | |
216 ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, | |
217 Node_List &old_new) { | |
218 LoopNode* head = loop->_head->as_Loop(); | |
3345 | 219 bool counted_loop = head->is_CountedLoop(); |
0 | 220 Node* entry = head->in(LoopNode::EntryControl); |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
221 _igvn.rehash_node_delayed(entry); |
0 | 222 IdealLoopTree* outer_loop = loop->_parent; |
223 | |
224 Node *cont = _igvn.intcon(1); | |
225 set_ctrl(cont, C->root()); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
226 Node* opq = new (C) Opaque1Node(C, cont); |
0 | 227 register_node(opq, outer_loop, entry, dom_depth(entry)); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
228 Node *bol = new (C) Conv2BNode(opq); |
0 | 229 register_node(bol, outer_loop, entry, dom_depth(entry)); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
230 IfNode* iff = new (C) IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN); |
0 | 231 register_node(iff, outer_loop, entry, dom_depth(entry)); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
232 ProjNode* iffast = new (C) IfTrueNode(iff); |
0 | 233 register_node(iffast, outer_loop, iff, dom_depth(iff)); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
234 ProjNode* ifslow = new (C) IfFalseNode(iff); |
0 | 235 register_node(ifslow, outer_loop, iff, dom_depth(iff)); |
236 | |
237 // Clone the loop body. The clone becomes the fast loop. The | |
2445 | 238 // original pre-header will (illegally) have 3 control users |
239 // (old & new loops & new if). | |
0 | 240 clone_loop(loop, old_new, dom_depth(head), iff); |
241 assert(old_new[head->_idx]->is_Loop(), "" ); | |
242 | |
243 // Fast (true) control | |
3345 | 244 Node* iffast_pred = clone_loop_predicates(entry, iffast, !counted_loop); |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
245 _igvn.replace_input_of(head, LoopNode::EntryControl, iffast_pred); |
2445 | 246 set_idom(head, iffast_pred, dom_depth(head)); |
0 | 247 |
248 // Slow (false) control | |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3345
diff
changeset
|
249 Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); |
0 | 250 LoopNode* slow_head = old_new[head->_idx]->as_Loop(); |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3845
diff
changeset
|
251 _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow_pred); |
2445 | 252 set_idom(slow_head, ifslow_pred, dom_depth(slow_head)); |
0 | 253 |
254 recompute_dom_depth(); | |
255 | |
256 return iffast; | |
257 } |