author | ctornqvi |
Fri, 13 Feb 2015 05:17:41 -0800 | |
changeset 28957 | 75ca61f0b7c7 |
parent 28643 | a665e19ca007 |
child 29086 | 74100114a95a |
permissions | -rw-r--r-- |
1 | 1 |
/* |
25926
486f1571b70f
8054081: Crashes with assert "modified node is not on IGVN._worklist"
thartmann
parents:
25913
diff
changeset
|
2 |
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. |
1 | 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 |
* |
|
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
5251
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
5251
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
5251
diff
changeset
|
21 |
* questions. |
1 | 22 |
* |
23 |
*/ |
|
24 |
||
7397 | 25 |
#include "precompiled.hpp" |
26 |
#include "compiler/compileLog.hpp" |
|
27 |
#include "libadt/vectset.hpp" |
|
28 |
#include "opto/addnode.hpp" |
|
29 |
#include "opto/callnode.hpp" |
|
23528 | 30 |
#include "opto/castnode.hpp" |
7397 | 31 |
#include "opto/cfgnode.hpp" |
32 |
#include "opto/compile.hpp" |
|
23528 | 33 |
#include "opto/convertnode.hpp" |
7397 | 34 |
#include "opto/locknode.hpp" |
35 |
#include "opto/loopnode.hpp" |
|
36 |
#include "opto/macro.hpp" |
|
37 |
#include "opto/memnode.hpp" |
|
23528 | 38 |
#include "opto/narrowptrnode.hpp" |
7397 | 39 |
#include "opto/node.hpp" |
23528 | 40 |
#include "opto/opaquenode.hpp" |
7397 | 41 |
#include "opto/phaseX.hpp" |
42 |
#include "opto/rootnode.hpp" |
|
43 |
#include "opto/runtime.hpp" |
|
44 |
#include "opto/subnode.hpp" |
|
45 |
#include "opto/type.hpp" |
|
46 |
#include "runtime/sharedRuntime.hpp" |
|
1 | 47 |
|
48 |
||
49 |
// |
|
50 |
// Replace any references to "oldref" in inputs to "use" with "newref". |
|
51 |
// Returns the number of replacements made. |
|
52 |
// |
|
53 |
int PhaseMacroExpand::replace_input(Node *use, Node *oldref, Node *newref) { |
|
54 |
int nreplacements = 0; |
|
55 |
uint req = use->req(); |
|
56 |
for (uint j = 0; j < use->len(); j++) { |
|
57 |
Node *uin = use->in(j); |
|
58 |
if (uin == oldref) { |
|
59 |
if (j < req) |
|
60 |
use->set_req(j, newref); |
|
61 |
else |
|
62 |
use->set_prec(j, newref); |
|
63 |
nreplacements++; |
|
64 |
} else if (j >= req && uin == NULL) { |
|
65 |
break; |
|
66 |
} |
|
67 |
} |
|
68 |
return nreplacements; |
|
69 |
} |
|
70 |
||
71 |
void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcall) { |
|
72 |
// Copy debug information and adjust JVMState information |
|
73 |
uint old_dbg_start = oldcall->tf()->domain()->cnt(); |
|
74 |
uint new_dbg_start = newcall->tf()->domain()->cnt(); |
|
75 |
int jvms_adj = new_dbg_start - old_dbg_start; |
|
76 |
assert (new_dbg_start == newcall->req(), "argument count mismatch"); |
|
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
77 |
|
19708
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
78 |
// SafePointScalarObject node could be referenced several times in debug info. |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
79 |
// Use Dict to record cloned nodes. |
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
80 |
Dict* sosn_map = new Dict(cmpkey,hashkey); |
1 | 81 |
for (uint i = old_dbg_start; i < oldcall->req(); i++) { |
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
82 |
Node* old_in = oldcall->in(i); |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
83 |
// Clone old SafePointScalarObjectNodes, adjusting their field contents. |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
84 |
if (old_in != NULL && old_in->is_SafePointScalarObject()) { |
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
85 |
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject(); |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
86 |
uint old_unique = C->unique(); |
19708
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
87 |
Node* new_in = old_sosn->clone(sosn_map); |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
88 |
if (old_unique != C->unique()) { // New node? |
11191 | 89 |
new_in->set_req(0, C->root()); // reset control edge |
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
90 |
new_in = transform_later(new_in); // Register new node. |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
91 |
} |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
92 |
old_in = new_in; |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
93 |
} |
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
94 |
newcall->add_req(old_in); |
1 | 95 |
} |
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
96 |
|
26180
2fbed11af70e
8055153: nsk/stress/jck60/jck60014 crashes on sparc
roland
parents:
26166
diff
changeset
|
97 |
// JVMS may be shared so clone it before we modify it |
2fbed11af70e
8055153: nsk/stress/jck60/jck60014 crashes on sparc
roland
parents:
26166
diff
changeset
|
98 |
newcall->set_jvms(oldcall->jvms() != NULL ? oldcall->jvms()->clone_deep(C) : NULL); |
1 | 99 |
for (JVMState *jvms = newcall->jvms(); jvms != NULL; jvms = jvms->caller()) { |
100 |
jvms->set_map(newcall); |
|
101 |
jvms->set_locoff(jvms->locoff()+jvms_adj); |
|
102 |
jvms->set_stkoff(jvms->stkoff()+jvms_adj); |
|
103 |
jvms->set_monoff(jvms->monoff()+jvms_adj); |
|
236
9a04268c8eea
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
1
diff
changeset
|
104 |
jvms->set_scloff(jvms->scloff()+jvms_adj); |
1 | 105 |
jvms->set_endoff(jvms->endoff()+jvms_adj); |
106 |
} |
|
107 |
} |
|
108 |
||
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
109 |
Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
110 |
Node* cmp; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
111 |
if (mask != 0) { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
112 |
Node* and_node = transform_later(new AndXNode(word, MakeConX(mask))); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
113 |
cmp = transform_later(new CmpXNode(and_node, MakeConX(bits))); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
114 |
} else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
115 |
cmp = word; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
116 |
} |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
117 |
Node* bol = transform_later(new BoolNode(cmp, BoolTest::ne)); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
118 |
IfNode* iff = new IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
119 |
transform_later(iff); |
1 | 120 |
|
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
121 |
// Fast path taken. |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
122 |
Node *fast_taken = transform_later(new IfFalseNode(iff)); |
1 | 123 |
|
124 |
// Fast path not-taken, i.e. slow path |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
125 |
Node *slow_taken = transform_later(new IfTrueNode(iff)); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
126 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
127 |
if (return_fast_path) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
128 |
region->init_req(edge, slow_taken); // Capture slow-control |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
129 |
return fast_taken; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
130 |
} else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
131 |
region->init_req(edge, fast_taken); // Capture fast-control |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
132 |
return slow_taken; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
133 |
} |
1 | 134 |
} |
135 |
||
136 |
//--------------------copy_predefined_input_for_runtime_call-------------------- |
|
137 |
void PhaseMacroExpand::copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call) { |
|
138 |
// Set fixed predefined input arguments |
|
139 |
call->init_req( TypeFunc::Control, ctrl ); |
|
140 |
call->init_req( TypeFunc::I_O , oldcall->in( TypeFunc::I_O) ); |
|
141 |
call->init_req( TypeFunc::Memory , oldcall->in( TypeFunc::Memory ) ); // ????? |
|
142 |
call->init_req( TypeFunc::ReturnAdr, oldcall->in( TypeFunc::ReturnAdr ) ); |
|
143 |
call->init_req( TypeFunc::FramePtr, oldcall->in( TypeFunc::FramePtr ) ); |
|
144 |
} |
|
145 |
||
146 |
//------------------------------make_slow_call--------------------------------- |
|
147 |
CallNode* PhaseMacroExpand::make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call, const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1) { |
|
148 |
||
149 |
// Slow-path call |
|
150 |
CallNode *call = leaf_name |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
151 |
? (CallNode*)new CallLeafNode ( slow_call_type, slow_call, leaf_name, TypeRawPtr::BOTTOM ) |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
152 |
: (CallNode*)new CallStaticJavaNode( slow_call_type, slow_call, OptoRuntime::stub_name(slow_call), oldcall->jvms()->bci(), TypeRawPtr::BOTTOM ); |
1 | 153 |
|
154 |
// Slow path call has no side-effects, uses few values |
|
155 |
copy_predefined_input_for_runtime_call(slow_path, oldcall, call ); |
|
156 |
if (parm0 != NULL) call->init_req(TypeFunc::Parms+0, parm0); |
|
157 |
if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1); |
|
158 |
copy_call_debug_info(oldcall, call); |
|
159 |
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. |
|
5901
c046f8e9c52b
6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents:
5889
diff
changeset
|
160 |
_igvn.replace_node(oldcall, call); |
1 | 161 |
transform_later(call); |
162 |
||
163 |
return call; |
|
164 |
} |
|
165 |
||
166 |
void PhaseMacroExpand::extract_call_projections(CallNode *call) { |
|
167 |
_fallthroughproj = NULL; |
|
168 |
_fallthroughcatchproj = NULL; |
|
169 |
_ioproj_fallthrough = NULL; |
|
170 |
_ioproj_catchall = NULL; |
|
171 |
_catchallcatchproj = NULL; |
|
172 |
_memproj_fallthrough = NULL; |
|
173 |
_memproj_catchall = NULL; |
|
174 |
_resproj = NULL; |
|
175 |
for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) { |
|
176 |
ProjNode *pn = call->fast_out(i)->as_Proj(); |
|
177 |
switch (pn->_con) { |
|
178 |
case TypeFunc::Control: |
|
179 |
{ |
|
180 |
// For Control (fallthrough) and I_O (catch_all_index) we have CatchProj -> Catch -> Proj |
|
181 |
_fallthroughproj = pn; |
|
182 |
DUIterator_Fast jmax, j = pn->fast_outs(jmax); |
|
183 |
const Node *cn = pn->fast_out(j); |
|
184 |
if (cn->is_Catch()) { |
|
185 |
ProjNode *cpn = NULL; |
|
186 |
for (DUIterator_Fast kmax, k = cn->fast_outs(kmax); k < kmax; k++) { |
|
187 |
cpn = cn->fast_out(k)->as_Proj(); |
|
188 |
assert(cpn->is_CatchProj(), "must be a CatchProjNode"); |
|
189 |
if (cpn->_con == CatchProjNode::fall_through_index) |
|
190 |
_fallthroughcatchproj = cpn; |
|
191 |
else { |
|
192 |
assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index."); |
|
193 |
_catchallcatchproj = cpn; |
|
194 |
} |
|
195 |
} |
|
196 |
} |
|
197 |
break; |
|
198 |
} |
|
199 |
case TypeFunc::I_O: |
|
200 |
if (pn->_is_io_use) |
|
201 |
_ioproj_catchall = pn; |
|
202 |
else |
|
203 |
_ioproj_fallthrough = pn; |
|
204 |
break; |
|
205 |
case TypeFunc::Memory: |
|
206 |
if (pn->_is_io_use) |
|
207 |
_memproj_catchall = pn; |
|
208 |
else |
|
209 |
_memproj_fallthrough = pn; |
|
210 |
break; |
|
211 |
case TypeFunc::Parms: |
|
212 |
_resproj = pn; |
|
213 |
break; |
|
214 |
default: |
|
215 |
assert(false, "unexpected projection from allocation node."); |
|
216 |
} |
|
217 |
} |
|
218 |
||
219 |
} |
|
220 |
||
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
221 |
// Eliminate a card mark sequence. p2x is a ConvP2XNode |
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
222 |
void PhaseMacroExpand::eliminate_card_mark(Node* p2x) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
223 |
assert(p2x->Opcode() == Op_CastP2X, "ConvP2XNode required"); |
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
224 |
if (!UseG1GC) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
225 |
// vanilla/CMS post barrier |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
226 |
Node *shift = p2x->unique_out(); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
227 |
Node *addp = shift->unique_out(); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
228 |
for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) { |
9331 | 229 |
Node *mem = addp->last_out(j); |
230 |
if (UseCondCardMark && mem->is_Load()) { |
|
231 |
assert(mem->Opcode() == Op_LoadB, "unexpected code shape"); |
|
232 |
// The load is checking if the card has been written so |
|
233 |
// replace it with zero to fold the test. |
|
234 |
_igvn.replace_node(mem, intcon(0)); |
|
235 |
continue; |
|
236 |
} |
|
237 |
assert(mem->is_Store(), "store required"); |
|
238 |
_igvn.replace_node(mem, mem->in(MemNode::Memory)); |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
239 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
240 |
} else { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
241 |
// G1 pre/post barriers |
11724
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
242 |
assert(p2x->outcnt() <= 2, "expects 1 or 2 users: Xor and URShift nodes"); |
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
243 |
// It could be only one user, URShift node, in Object.clone() instrinsic |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
244 |
// but the new allocation is passed to arraycopy stub and it could not |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
245 |
// be scalar replaced. So we don't check the case. |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
246 |
|
11724
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
247 |
// An other case of only one user (Xor) is when the value check for NULL |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
248 |
// in G1 post barrier is folded after CCP so the code which used URShift |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
249 |
// is removed. |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
250 |
|
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
251 |
// Take Region node before eliminating post barrier since it also |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
252 |
// eliminates CastP2X node when it has only one user. |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
253 |
Node* this_region = p2x->in(0); |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
254 |
assert(this_region != NULL, ""); |
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
255 |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
256 |
// Remove G1 post barrier. |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
257 |
|
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
258 |
// Search for CastP2X->Xor->URShift->Cmp path which |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
259 |
// checks if the store done to a different from the value's region. |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
260 |
// And replace Cmp with #0 (false) to collapse G1 post barrier. |
28643
a665e19ca007
8066312: Add new Node* Node::find_out(int opc) method.
zmajo
parents:
28039
diff
changeset
|
261 |
Node* xorx = p2x->find_out_with(Op_XorX); |
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
262 |
assert(xorx != NULL, "missing G1 post barrier"); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
263 |
Node* shift = xorx->unique_out(); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
264 |
Node* cmpx = shift->unique_out(); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
265 |
assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() && |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
266 |
cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne, |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
267 |
"missing region check in G1 post barrier"); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
268 |
_igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
269 |
|
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
270 |
// Remove G1 pre barrier. |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
271 |
|
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
272 |
// Search "if (marking != 0)" check and set it to "false". |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
273 |
// There is no G1 pre barrier if previous stored value is NULL |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
274 |
// (for example, after initialization). |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
275 |
if (this_region->is_Region() && this_region->req() == 3) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
276 |
int ind = 1; |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
277 |
if (!this_region->in(ind)->is_IfFalse()) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
278 |
ind = 2; |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
279 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
280 |
if (this_region->in(ind)->is_IfFalse()) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
281 |
Node* bol = this_region->in(ind)->in(0)->in(1); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
282 |
assert(bol->is_Bool(), ""); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
283 |
cmpx = bol->in(1); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
284 |
if (bol->as_Bool()->_test._test == BoolTest::ne && |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
285 |
cmpx->is_Cmp() && cmpx->in(2) == intcon(0) && |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
286 |
cmpx->in(1)->is_Load()) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
287 |
Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
288 |
const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
289 |
PtrQueue::byte_offset_of_active()); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
290 |
if (adr->is_AddP() && adr->in(AddPNode::Base) == top() && |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
291 |
adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal && |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
292 |
adr->in(AddPNode::Offset) == MakeConX(marking_offset)) { |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
293 |
_igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
294 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
295 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
296 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
297 |
} |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
298 |
// Now CastP2X can be removed since it is used only on dead path |
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
299 |
// which currently still alive until igvn optimize it. |
11724
1500e51fdcbf
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
11460
diff
changeset
|
300 |
assert(p2x->outcnt() == 0 || p2x->unique_out()->Opcode() == Op_URShiftX, ""); |
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
2867
diff
changeset
|
301 |
_igvn.replace_node(p2x, top()); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
302 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
303 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
304 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
305 |
// Search for a memory operation for the specified memory slice. |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
306 |
static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
307 |
Node *orig_mem = mem; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
308 |
Node *alloc_mem = alloc->in(TypeFunc::Memory); |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
309 |
const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr(); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
310 |
while (true) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
311 |
if (mem == alloc_mem || mem == start_mem ) { |
2131 | 312 |
return mem; // hit one of our sentinels |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
313 |
} else if (mem->is_MergeMem()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
314 |
mem = mem->as_MergeMem()->memory_at(alias_idx); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
315 |
} else if (mem->is_Proj() && mem->as_Proj()->_con == TypeFunc::Memory) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
316 |
Node *in = mem->in(0); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
317 |
// we can safely skip over safepoints, calls, locks and membars because we |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
318 |
// already know that the object is safe to eliminate. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
319 |
if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
320 |
return in; |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
321 |
} else if (in->is_Call()) { |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
322 |
CallNode *call = in->as_Call(); |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
323 |
if (!call->may_modify(tinst, phase)) { |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
324 |
mem = call->in(TypeFunc::Memory); |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
325 |
} |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
326 |
mem = in->in(TypeFunc::Memory); |
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
327 |
} else if (in->is_MemBar()) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
328 |
mem = in->in(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
329 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
330 |
assert(false, "unexpected projection"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
331 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
332 |
} else if (mem->is_Store()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
333 |
const TypePtr* atype = mem->as_Store()->adr_type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
334 |
int adr_idx = Compile::current()->get_alias_index(atype); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
335 |
if (adr_idx == alias_idx) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
336 |
assert(atype->isa_oopptr(), "address type must be oopptr"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
337 |
int adr_offset = atype->offset(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
338 |
uint adr_iid = atype->is_oopptr()->instance_id(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
339 |
// Array elements references have the same alias_idx |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
340 |
// but different offset and different instance_id. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
341 |
if (adr_offset == offset && adr_iid == alloc->_idx) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
342 |
return mem; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
343 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
344 |
assert(adr_idx == Compile::AliasIdxRaw, "address must match or be raw"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
345 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
346 |
mem = mem->in(MemNode::Memory); |
4470
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
347 |
} else if (mem->is_ClearArray()) { |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
348 |
if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) { |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
349 |
// Can not bypass initialization of the instance |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
350 |
// we are looking. |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
351 |
debug_only(intptr_t offset;) |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
352 |
assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity"); |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
353 |
InitializeNode* init = alloc->as_Allocate()->initialization(); |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
354 |
// We are looking for stored value, return Initialize node |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
355 |
// or memory edge from Allocate node. |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
356 |
if (init != NULL) |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
357 |
return init; |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
358 |
else |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
359 |
return alloc->in(TypeFunc::Memory); // It will produce zero value (see callers). |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
360 |
} |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
361 |
// Otherwise skip it (the call updated 'mem' value). |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
362 |
} else if (mem->Opcode() == Op_SCMemProj) { |
15242
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
363 |
mem = mem->in(0); |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
364 |
Node* adr = NULL; |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
365 |
if (mem->is_LoadStore()) { |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
366 |
adr = mem->in(MemNode::Address); |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
367 |
} else { |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
368 |
assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
369 |
adr = mem->in(3); // Destination array |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
370 |
} |
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
371 |
const TypePtr* atype = adr->bottom_type()->is_ptr(); |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
372 |
int adr_idx = Compile::current()->get_alias_index(atype); |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
373 |
if (adr_idx == alias_idx) { |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
374 |
assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
375 |
return NULL; |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
376 |
} |
15242
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
377 |
mem = mem->in(MemNode::Memory); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
378 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
379 |
return mem; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
380 |
} |
955 | 381 |
assert(mem != orig_mem, "dead memory loop"); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
382 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
383 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
384 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
385 |
// |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
386 |
// Given a Memory Phi, compute a value Phi containing the values from stores |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
387 |
// on the input paths. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
388 |
// Note: this function is recursive, its depth is limied by the "level" argument |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
389 |
// Returns the computed Phi, or NULL if it cannot compute it. |
955 | 390 |
Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) { |
391 |
assert(mem->is_Phi(), "sanity"); |
|
392 |
int alias_idx = C->get_alias_index(adr_t); |
|
393 |
int offset = adr_t->offset(); |
|
394 |
int instance_id = adr_t->instance_id(); |
|
395 |
||
396 |
// Check if an appropriate value phi already exists. |
|
397 |
Node* region = mem->in(0); |
|
398 |
for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { |
|
399 |
Node* phi = region->fast_out(k); |
|
400 |
if (phi->is_Phi() && phi != mem && |
|
401 |
phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { |
|
402 |
return phi; |
|
403 |
} |
|
404 |
} |
|
405 |
// Check if an appropriate new value phi already exists. |
|
10011
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
9977
diff
changeset
|
406 |
Node* new_phi = value_phis->find(mem->_idx); |
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
9977
diff
changeset
|
407 |
if (new_phi != NULL) |
e8b38f7b9959
7044738: Loop unroll optimization causes incorrect result
kvn
parents:
9977
diff
changeset
|
408 |
return new_phi; |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
409 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
410 |
if (level <= 0) { |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
411 |
return NULL; // Give up: phi tree too deep |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
412 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
413 |
Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
414 |
Node *alloc_mem = alloc->in(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
415 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
416 |
uint length = mem->req(); |
13195 | 417 |
GrowableArray <Node *> values(length, length, NULL, false); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
418 |
|
955 | 419 |
// create a new Phi for the value |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
420 |
PhiNode *phi = new PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); |
955 | 421 |
transform_later(phi); |
422 |
value_phis->push(phi, mem->_idx); |
|
423 |
||
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
424 |
for (uint j = 1; j < length; j++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
425 |
Node *in = mem->in(j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
426 |
if (in == NULL || in->is_top()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
427 |
values.at_put(j, in); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
428 |
} else { |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
429 |
Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc, &_igvn); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
430 |
if (val == start_mem || val == alloc_mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
431 |
// hit a sentinel, return appropriate 0 value |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
432 |
values.at_put(j, _igvn.zerocon(ft)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
433 |
continue; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
434 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
435 |
if (val->is_Initialize()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
436 |
val = val->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
437 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
438 |
if (val == NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
439 |
return NULL; // can't find a value on this path |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
440 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
441 |
if (val == mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
442 |
values.at_put(j, mem); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
443 |
} else if (val->is_Store()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
444 |
values.at_put(j, val->in(MemNode::ValueIn)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
445 |
} else if(val->is_Proj() && val->in(0) == alloc) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
446 |
values.at_put(j, _igvn.zerocon(ft)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
447 |
} else if (val->is_Phi()) { |
955 | 448 |
val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1); |
449 |
if (val == NULL) { |
|
450 |
return NULL; |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
451 |
} |
955 | 452 |
values.at_put(j, val); |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
453 |
} else if (val->Opcode() == Op_SCMemProj) { |
15242
695bb216be99
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
14623
diff
changeset
|
454 |
assert(val->in(0)->is_LoadStore() || val->in(0)->Opcode() == Op_EncodeISOArray, "sanity"); |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
455 |
assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
456 |
return NULL; |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
457 |
} else { |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
458 |
#ifdef ASSERT |
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
459 |
val->dump(); |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
460 |
assert(false, "unknown node on this path"); |
2110
40e42c95ac39
6802499: EA: assert(false,"unknown node on this path")
kvn
parents:
2029
diff
changeset
|
461 |
#endif |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
462 |
return NULL; // unknown node on this path |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
463 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
464 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
465 |
} |
955 | 466 |
// Set Phi's inputs |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
467 |
for (uint j = 1; j < length; j++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
468 |
if (values.at(j) == mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
469 |
phi->init_req(j, phi); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
470 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
471 |
phi->init_req(j, values.at(j)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
472 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
473 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
474 |
return phi; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
475 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
476 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
477 |
// Search the last value stored into the object's field. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
478 |
Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) { |
769 | 479 |
assert(adr_t->is_known_instance_field(), "instance required"); |
480 |
int instance_id = adr_t->instance_id(); |
|
481 |
assert((uint)instance_id == alloc->_idx, "wrong allocation"); |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
482 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
483 |
int alias_idx = C->get_alias_index(adr_t); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
484 |
int offset = adr_t->offset(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
485 |
Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
486 |
Node *alloc_ctrl = alloc->in(TypeFunc::Control); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
487 |
Node *alloc_mem = alloc->in(TypeFunc::Memory); |
955 | 488 |
Arena *a = Thread::current()->resource_area(); |
489 |
VectorSet visited(a); |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
490 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
491 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
492 |
bool done = sfpt_mem == alloc_mem; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
493 |
Node *mem = sfpt_mem; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
494 |
while (!done) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
495 |
if (visited.test_set(mem->_idx)) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
496 |
return NULL; // found a loop, give up |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
497 |
} |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
498 |
mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc, &_igvn); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
499 |
if (mem == start_mem || mem == alloc_mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
500 |
done = true; // hit a sentinel, return appropriate 0 value |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
501 |
} else if (mem->is_Initialize()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
502 |
mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
503 |
if (mem == NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
504 |
done = true; // Something go wrong. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
505 |
} else if (mem->is_Store()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
506 |
const TypePtr* atype = mem->as_Store()->adr_type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
507 |
assert(C->get_alias_index(atype) == Compile::AliasIdxRaw, "store is correct memory slice"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
508 |
done = true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
509 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
510 |
} else if (mem->is_Store()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
511 |
const TypeOopPtr* atype = mem->as_Store()->adr_type()->isa_oopptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
512 |
assert(atype != NULL, "address type must be oopptr"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
513 |
assert(C->get_alias_index(atype) == alias_idx && |
769 | 514 |
atype->is_known_instance_field() && atype->offset() == offset && |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
515 |
atype->instance_id() == instance_id, "store is correct memory slice"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
516 |
done = true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
517 |
} else if (mem->is_Phi()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
518 |
// try to find a phi's unique input |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
519 |
Node *unique_input = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
520 |
Node *top = C->top(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
521 |
for (uint i = 1; i < mem->req(); i++) { |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
522 |
Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc, &_igvn); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
523 |
if (n == NULL || n == top || n == mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
524 |
continue; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
525 |
} else if (unique_input == NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
526 |
unique_input = n; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
527 |
} else if (unique_input != n) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
528 |
unique_input = top; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
529 |
break; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
530 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
531 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
532 |
if (unique_input != NULL && unique_input != top) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
533 |
mem = unique_input; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
534 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
535 |
done = true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
536 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
537 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
538 |
assert(false, "unexpected node"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
539 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
540 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
541 |
if (mem != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
542 |
if (mem == start_mem || mem == alloc_mem) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
543 |
// hit a sentinel, return appropriate 0 value |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
544 |
return _igvn.zerocon(ft); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
545 |
} else if (mem->is_Store()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
546 |
return mem->in(MemNode::ValueIn); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
547 |
} else if (mem->is_Phi()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
548 |
// attempt to produce a Phi reflecting the values on the input paths of the Phi |
955 | 549 |
Node_Stack value_phis(a, 8); |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
550 |
Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
551 |
if (phi != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
552 |
return phi; |
955 | 553 |
} else { |
554 |
// Kill all new Phis |
|
555 |
while(value_phis.is_nonempty()) { |
|
556 |
Node* n = value_phis.node(); |
|
5901
c046f8e9c52b
6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents:
5889
diff
changeset
|
557 |
_igvn.replace_node(n, C->top()); |
955 | 558 |
value_phis.pop(); |
559 |
} |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
560 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
561 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
562 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
563 |
// Something go wrong. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
564 |
return NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
565 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
566 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
567 |
// Check the possibility of scalar replacement. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
568 |
bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
569 |
// Scan the uses of the allocation to check for anything that would |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
570 |
// prevent us from eliminating it. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
571 |
NOT_PRODUCT( const char* fail_eliminate = NULL; ) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
572 |
DEBUG_ONLY( Node* disq_node = NULL; ) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
573 |
bool can_eliminate = true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
574 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
575 |
Node* res = alloc->result_cast(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
576 |
const TypeOopPtr* res_type = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
577 |
if (res == NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
578 |
// All users were eliminated. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
579 |
} else if (!res->is_CheckCastPP()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
580 |
NOT_PRODUCT(fail_eliminate = "Allocation does not have unique CheckCastPP";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
581 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
582 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
583 |
res_type = _igvn.type(res)->isa_oopptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
584 |
if (res_type == NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
585 |
NOT_PRODUCT(fail_eliminate = "Neither instance or array allocation";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
586 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
587 |
} else if (res_type->isa_aryptr()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
588 |
int length = alloc->in(AllocateNode::ALength)->find_int_con(-1); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
589 |
if (length < 0) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
590 |
NOT_PRODUCT(fail_eliminate = "Array's size is not constant";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
591 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
592 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
593 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
594 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
595 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
596 |
if (can_eliminate && res != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
597 |
for (DUIterator_Fast jmax, j = res->fast_outs(jmax); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
598 |
j < jmax && can_eliminate; j++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
599 |
Node* use = res->fast_out(j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
600 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
601 |
if (use->is_AddP()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
602 |
const TypePtr* addp_type = _igvn.type(use)->is_ptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
603 |
int offset = addp_type->offset(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
604 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
605 |
if (offset == Type::OffsetTop || offset == Type::OffsetBot) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
606 |
NOT_PRODUCT(fail_eliminate = "Undefined field referrence";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
607 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
608 |
break; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
609 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
610 |
for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
611 |
k < kmax && can_eliminate; k++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
612 |
Node* n = use->fast_out(k); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
613 |
if (!n->is_Store() && n->Opcode() != Op_CastP2X) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
614 |
DEBUG_ONLY(disq_node = n;) |
961
7fb3b13d4205
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
955
diff
changeset
|
615 |
if (n->is_Load() || n->is_LoadStore()) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
616 |
NOT_PRODUCT(fail_eliminate = "Field load";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
617 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
618 |
NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
619 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
620 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
621 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
622 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
623 |
} else if (use->is_SafePoint()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
624 |
SafePointNode* sfpt = use->as_SafePoint(); |
594
9f4474e5dbaf
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
589
diff
changeset
|
625 |
if (sfpt->is_Call() && sfpt->as_Call()->has_non_debug_use(res)) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
626 |
// Object is passed as argument. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
627 |
DEBUG_ONLY(disq_node = use;) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
628 |
NOT_PRODUCT(fail_eliminate = "Object is passed as argument";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
629 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
630 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
631 |
Node* sfptMem = sfpt->memory(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
632 |
if (sfptMem == NULL || sfptMem->is_top()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
633 |
DEBUG_ONLY(disq_node = use;) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
634 |
NOT_PRODUCT(fail_eliminate = "NULL or TOP memory";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
635 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
636 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
637 |
safepoints.append_if_missing(sfpt); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
638 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
639 |
} else if (use->Opcode() != Op_CastP2X) { // CastP2X is used by card mark |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
640 |
if (use->is_Phi()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
641 |
if (use->outcnt() == 1 && use->unique_out()->Opcode() == Op_Return) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
642 |
NOT_PRODUCT(fail_eliminate = "Object is return value";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
643 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
644 |
NOT_PRODUCT(fail_eliminate = "Object is referenced by Phi";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
645 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
646 |
DEBUG_ONLY(disq_node = use;) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
647 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
648 |
if (use->Opcode() == Op_Return) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
649 |
NOT_PRODUCT(fail_eliminate = "Object is return value";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
650 |
}else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
651 |
NOT_PRODUCT(fail_eliminate = "Object is referenced by node";) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
652 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
653 |
DEBUG_ONLY(disq_node = use;) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
654 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
655 |
can_eliminate = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
656 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
657 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
658 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
659 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
660 |
#ifndef PRODUCT |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
661 |
if (PrintEliminateAllocations) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
662 |
if (can_eliminate) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
663 |
tty->print("Scalar "); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
664 |
if (res == NULL) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
665 |
alloc->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
666 |
else |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
667 |
res->dump(); |
17383 | 668 |
} else if (alloc->_is_scalar_replaceable) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
669 |
tty->print("NotScalar (%s)", fail_eliminate); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
670 |
if (res == NULL) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
671 |
alloc->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
672 |
else |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
673 |
res->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
674 |
#ifdef ASSERT |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
675 |
if (disq_node != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
676 |
tty->print(" >>>> "); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
677 |
disq_node->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
678 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
679 |
#endif /*ASSERT*/ |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
680 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
681 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
682 |
#endif |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
683 |
return can_eliminate; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
684 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
685 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
686 |
// Do scalar replacement. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
687 |
bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
688 |
GrowableArray <SafePointNode *> safepoints_done; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
689 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
690 |
ciKlass* klass = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
691 |
ciInstanceKlass* iklass = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
692 |
int nfields = 0; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
693 |
int array_base; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
694 |
int element_size; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
695 |
BasicType basic_elem_type; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
696 |
ciType* elem_type; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
697 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
698 |
Node* res = alloc->result_cast(); |
25935
59b08808cb9c
8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943
roland
parents:
25926
diff
changeset
|
699 |
assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result"); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
700 |
const TypeOopPtr* res_type = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
701 |
if (res != NULL) { // Could be NULL when there are no users |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
702 |
res_type = _igvn.type(res)->isa_oopptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
703 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
704 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
705 |
if (res != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
706 |
klass = res_type->klass(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
707 |
if (res_type->isa_instptr()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
708 |
// find the fields of the class which will be needed for safepoint debug information |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
709 |
assert(klass->is_instance_klass(), "must be an instance klass."); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
710 |
iklass = klass->as_instance_klass(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
711 |
nfields = iklass->nof_nonstatic_fields(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
712 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
713 |
// find the array's elements which will be needed for safepoint debug information |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
714 |
nfields = alloc->in(AllocateNode::ALength)->find_int_con(-1); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
715 |
assert(klass->is_array_klass() && nfields >= 0, "must be an array klass."); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
716 |
elem_type = klass->as_array_klass()->element_type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
717 |
basic_elem_type = elem_type->basic_type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
718 |
array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
719 |
element_size = type2aelembytes(basic_elem_type); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
720 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
721 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
722 |
// |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
723 |
// Process the safepoint uses |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
724 |
// |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
725 |
while (safepoints.length() > 0) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
726 |
SafePointNode* sfpt = safepoints.pop(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
727 |
Node* mem = sfpt->memory(); |
19708
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
728 |
assert(sfpt->jvms() != NULL, "missed JVMS"); |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
729 |
// Fields of scalar objs are referenced only at the end |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
730 |
// of regular debuginfo at the last (youngest) JVMS. |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
731 |
// Record relative start index. |
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
732 |
uint first_ind = (sfpt->req() - sfpt->jvms()->scloff()); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
733 |
SafePointScalarObjectNode* sobj = new SafePointScalarObjectNode(res_type, |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
734 |
#ifdef ASSERT |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
735 |
alloc, |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
736 |
#endif |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
737 |
first_ind, nfields); |
11191 | 738 |
sobj->init_req(0, C->root()); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
739 |
transform_later(sobj); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
740 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
741 |
// Scan object's fields adding an input to the safepoint for each field. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
742 |
for (int j = 0; j < nfields; j++) { |
1068
720698d9c89b
6741738: TypePtr::add_offset() set incorrect offset when the add overflows
kvn
parents:
961
diff
changeset
|
743 |
intptr_t offset; |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
744 |
ciField* field = NULL; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
745 |
if (iklass != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
746 |
field = iklass->nonstatic_field_at(j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
747 |
offset = field->offset(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
748 |
elem_type = field->type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
749 |
basic_elem_type = field->layout_type(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
750 |
} else { |
1068
720698d9c89b
6741738: TypePtr::add_offset() set incorrect offset when the add overflows
kvn
parents:
961
diff
changeset
|
751 |
offset = array_base + j * (intptr_t)element_size; |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
752 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
753 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
754 |
const Type *field_type; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
755 |
// The next code is taken from Parse::do_get_xxx(). |
371
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
756 |
if (basic_elem_type == T_OBJECT || basic_elem_type == T_ARRAY) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
757 |
if (!elem_type->is_loaded()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
758 |
field_type = TypeInstPtr::BOTTOM; |
6177
12835feea156
6969569: assert(is_static() && is_constant()) failed: illegal call to constant_value()
kvn
parents:
5901
diff
changeset
|
759 |
} else if (field != NULL && field->is_constant() && field->is_static()) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
760 |
// This can happen if the constant oop is non-perm. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
761 |
ciObject* con = field->constant_value().as_object(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
762 |
// Do not "join" in the previous type; it doesn't add value, |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
763 |
// and may yield a vacuous result if the field is of interface type. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
764 |
field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
765 |
assert(field_type != NULL, "field singleton type must be consistent"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
766 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
767 |
field_type = TypeOopPtr::make_from_klass(elem_type->as_klass()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
768 |
} |
371
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
769 |
if (UseCompressedOops) { |
767
64fb1fd7186d
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
762
diff
changeset
|
770 |
field_type = field_type->make_narrowoop(); |
371
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
771 |
basic_elem_type = T_NARROWOOP; |
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
772 |
} |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
773 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
774 |
field_type = Type::get_const_basic_type(basic_elem_type); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
775 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
776 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
777 |
const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
778 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
779 |
Node *field_val = value_from_mem(mem, basic_elem_type, field_type, field_addr_type, alloc); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
780 |
if (field_val == NULL) { |
11191 | 781 |
// We weren't able to find a value for this field, |
782 |
// give up on eliminating this allocation. |
|
783 |
||
784 |
// Remove any extra entries we added to the safepoint. |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
785 |
uint last = sfpt->req() - 1; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
786 |
for (int k = 0; k < j; k++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
787 |
sfpt->del_req(last--); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
788 |
} |
25926
486f1571b70f
8054081: Crashes with assert "modified node is not on IGVN._worklist"
thartmann
parents:
25913
diff
changeset
|
789 |
_igvn._worklist.push(sfpt); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
790 |
// rollback processed safepoints |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
791 |
while (safepoints_done.length() > 0) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
792 |
SafePointNode* sfpt_done = safepoints_done.pop(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
793 |
// remove any extra entries we added to the safepoint |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
794 |
last = sfpt_done->req() - 1; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
795 |
for (int k = 0; k < nfields; k++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
796 |
sfpt_done->del_req(last--); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
797 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
798 |
JVMState *jvms = sfpt_done->jvms(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
799 |
jvms->set_endoff(sfpt_done->req()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
800 |
// Now make a pass over the debug information replacing any references |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
801 |
// to SafePointScalarObjectNode with the allocated object. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
802 |
int start = jvms->debug_start(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
803 |
int end = jvms->debug_end(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
804 |
for (int i = start; i < end; i++) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
805 |
if (sfpt_done->in(i)->is_SafePointScalarObject()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
806 |
SafePointScalarObjectNode* scobj = sfpt_done->in(i)->as_SafePointScalarObject(); |
19708
64e8c91f5f3e
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
17384
diff
changeset
|
807 |
if (scobj->first_index(jvms) == sfpt_done->req() && |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
808 |
scobj->n_fields() == (uint)nfields) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
809 |
assert(scobj->alloc() == alloc, "sanity"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
810 |
sfpt_done->set_req(i, res); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
811 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
812 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
813 |
} |
25926
486f1571b70f
8054081: Crashes with assert "modified node is not on IGVN._worklist"
thartmann
parents:
25913
diff
changeset
|
814 |
_igvn._worklist.push(sfpt_done); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
815 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
816 |
#ifndef PRODUCT |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
817 |
if (PrintEliminateAllocations) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
818 |
if (field != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
819 |
tty->print("=== At SafePoint node %d can't find value of Field: ", |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
820 |
sfpt->_idx); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
821 |
field->print(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
822 |
int field_idx = C->get_alias_index(field_addr_type); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
823 |
tty->print(" (alias_idx=%d)", field_idx); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
824 |
} else { // Array's element |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
825 |
tty->print("=== At SafePoint node %d can't find value of array element [%d]", |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
826 |
sfpt->_idx, j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
827 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
828 |
tty->print(", which prevents elimination of: "); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
829 |
if (res == NULL) |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
830 |
alloc->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
831 |
else |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
832 |
res->dump(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
833 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
834 |
#endif |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
835 |
return false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
836 |
} |
371
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
837 |
if (UseCompressedOops && field_type->isa_narrowoop()) { |
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
838 |
// Enable "DecodeN(EncodeP(Allocate)) --> Allocate" transformation |
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
839 |
// to be able scalar replace the allocation. |
767
64fb1fd7186d
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
762
diff
changeset
|
840 |
if (field_val->is_EncodeP()) { |
64fb1fd7186d
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
762
diff
changeset
|
841 |
field_val = field_val->in(1); |
64fb1fd7186d
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
762
diff
changeset
|
842 |
} else { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
843 |
field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type())); |
767
64fb1fd7186d
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
762
diff
changeset
|
844 |
} |
371
1aacedc9db7c
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
360
diff
changeset
|
845 |
} |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
846 |
sfpt->add_req(field_val); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
847 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
848 |
JVMState *jvms = sfpt->jvms(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
849 |
jvms->set_endoff(sfpt->req()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
850 |
// Now make a pass over the debug information replacing any references |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
851 |
// to the allocated object with "sobj" |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
852 |
int start = jvms->debug_start(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
853 |
int end = jvms->debug_end(); |
17383 | 854 |
sfpt->replace_edges_in_range(res, sobj, start, end); |
25913
81dbc151e91c
8040213: C2 does not put all modified nodes on IGVN worklist
thartmann
parents:
24923
diff
changeset
|
855 |
_igvn._worklist.push(sfpt); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
856 |
safepoints_done.append_if_missing(sfpt); // keep it for rollback |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
857 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
858 |
return true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
859 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
860 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
861 |
// Process users of eliminated allocation. |
17383 | 862 |
void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
863 |
Node* res = alloc->result_cast(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
864 |
if (res != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
865 |
for (DUIterator_Last jmin, j = res->last_outs(jmin); j >= jmin; ) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
866 |
Node *use = res->last_out(j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
867 |
uint oc1 = res->outcnt(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
868 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
869 |
if (use->is_AddP()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
870 |
for (DUIterator_Last kmin, k = use->last_outs(kmin); k >= kmin; ) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
871 |
Node *n = use->last_out(k); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
872 |
uint oc2 = use->outcnt(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
873 |
if (n->is_Store()) { |
4470
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
874 |
#ifdef ASSERT |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
875 |
// Verify that there is no dependent MemBarVolatile nodes, |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
876 |
// they should be removed during IGVN, see MemBarNode::Ideal(). |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
877 |
for (DUIterator_Fast pmax, p = n->fast_outs(pmax); |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
878 |
p < pmax; p++) { |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
879 |
Node* mb = n->fast_out(p); |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
880 |
assert(mb->is_Initialize() || !mb->is_MemBar() || |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
881 |
mb->req() <= MemBarNode::Precedent || |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
882 |
mb->in(MemBarNode::Precedent) != n, |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
883 |
"MemBarVolatile should be eliminated for non-escaping object"); |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
884 |
} |
1e6edcab3109
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
4450
diff
changeset
|
885 |
#endif |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
886 |
_igvn.replace_node(n, n->in(MemNode::Memory)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
887 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
888 |
eliminate_card_mark(n); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
889 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
890 |
k -= (oc2 - use->outcnt()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
891 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
892 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
893 |
eliminate_card_mark(use); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
894 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
895 |
j -= (oc1 - res->outcnt()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
896 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
897 |
assert(res->outcnt() == 0, "all uses of allocated objects must be deleted"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
898 |
_igvn.remove_dead_node(res); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
899 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
900 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
901 |
// |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
902 |
// Process other users of allocation's projections |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
903 |
// |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
904 |
if (_resproj != NULL && _resproj->outcnt() != 0) { |
17383 | 905 |
// First disconnect stores captured by Initialize node. |
906 |
// If Initialize node is eliminated first in the following code, |
|
907 |
// it will kill such stores and DUIterator_Last will assert. |
|
908 |
for (DUIterator_Fast jmax, j = _resproj->fast_outs(jmax); j < jmax; j++) { |
|
909 |
Node *use = _resproj->fast_out(j); |
|
910 |
if (use->is_AddP()) { |
|
911 |
// raw memory addresses used only by the initialization |
|
912 |
_igvn.replace_node(use, C->top()); |
|
913 |
--j; --jmax; |
|
914 |
} |
|
915 |
} |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
916 |
for (DUIterator_Last jmin, j = _resproj->last_outs(jmin); j >= jmin; ) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
917 |
Node *use = _resproj->last_out(j); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
918 |
uint oc1 = _resproj->outcnt(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
919 |
if (use->is_Initialize()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
920 |
// Eliminate Initialize node. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
921 |
InitializeNode *init = use->as_Initialize(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
922 |
assert(init->outcnt() <= 2, "only a control and memory projection expected"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
923 |
Node *ctrl_proj = init->proj_out(TypeFunc::Control); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
924 |
if (ctrl_proj != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
925 |
assert(init->in(TypeFunc::Control) == _fallthroughcatchproj, "allocation control projection"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
926 |
_igvn.replace_node(ctrl_proj, _fallthroughcatchproj); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
927 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
928 |
Node *mem_proj = init->proj_out(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
929 |
if (mem_proj != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
930 |
Node *mem = init->in(TypeFunc::Memory); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
931 |
#ifdef ASSERT |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
932 |
if (mem->is_MergeMem()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
933 |
assert(mem->in(TypeFunc::Memory) == _memproj_fallthrough, "allocation memory projection"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
934 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
935 |
assert(mem == _memproj_fallthrough, "allocation memory projection"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
936 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
937 |
#endif |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
938 |
_igvn.replace_node(mem_proj, mem); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
939 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
940 |
} else { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
941 |
assert(false, "only Initialize or AddP expected"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
942 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
943 |
j -= (oc1 - _resproj->outcnt()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
944 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
945 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
946 |
if (_fallthroughcatchproj != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
947 |
_igvn.replace_node(_fallthroughcatchproj, alloc->in(TypeFunc::Control)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
948 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
949 |
if (_memproj_fallthrough != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
950 |
_igvn.replace_node(_memproj_fallthrough, alloc->in(TypeFunc::Memory)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
951 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
952 |
if (_memproj_catchall != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
953 |
_igvn.replace_node(_memproj_catchall, C->top()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
954 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
955 |
if (_ioproj_fallthrough != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
956 |
_igvn.replace_node(_ioproj_fallthrough, alloc->in(TypeFunc::I_O)); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
957 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
958 |
if (_ioproj_catchall != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
959 |
_igvn.replace_node(_ioproj_catchall, C->top()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
960 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
961 |
if (_catchallcatchproj != NULL) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
962 |
_igvn.replace_node(_catchallcatchproj, C->top()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
963 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
964 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
965 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
966 |
bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { |
28039
bf5a8340bf8a
6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
roland
parents:
27645
diff
changeset
|
967 |
// Don't do scalar replacement if the frame can be popped by JVMTI: |
bf5a8340bf8a
6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
roland
parents:
27645
diff
changeset
|
968 |
// if reallocation fails during deoptimization we'll pop all |
bf5a8340bf8a
6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
roland
parents:
27645
diff
changeset
|
969 |
// interpreter frames for this compiled frame and that won't play |
bf5a8340bf8a
6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
roland
parents:
27645
diff
changeset
|
970 |
// nice with JVMTI popframe. |
bf5a8340bf8a
6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
roland
parents:
27645
diff
changeset
|
971 |
if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) { |
17383 | 972 |
return false; |
973 |
} |
|
974 |
Node* klass = alloc->in(AllocateNode::KlassNode); |
|
975 |
const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); |
|
976 |
Node* res = alloc->result_cast(); |
|
977 |
// Eliminate boxing allocations which are not used |
|
978 |
// regardless scalar replacable status. |
|
979 |
bool boxing_alloc = C->eliminate_boxing() && |
|
980 |
tklass->klass()->is_instance_klass() && |
|
981 |
tklass->klass()->as_instance_klass()->is_box_klass(); |
|
982 |
if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) { |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
983 |
return false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
984 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
985 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
986 |
extract_call_projections(alloc); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
987 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
988 |
GrowableArray <SafePointNode *> safepoints; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
989 |
if (!can_eliminate_allocation(alloc, safepoints)) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
990 |
return false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
991 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
992 |
|
17383 | 993 |
if (!alloc->_is_scalar_replaceable) { |
994 |
assert(res == NULL, "sanity"); |
|
995 |
// We can only eliminate allocation if all debug info references |
|
996 |
// are already replaced with SafePointScalarObject because |
|
997 |
// we can't search for a fields value without instance_id. |
|
998 |
if (safepoints.length() > 0) { |
|
999 |
return false; |
|
1000 |
} |
|
1001 |
} |
|
1002 |
||
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1003 |
if (!scalar_replacement(alloc, safepoints)) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1004 |
return false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1005 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1006 |
|
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1007 |
CompileLog* log = C->log(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1008 |
if (log != NULL) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1009 |
log->head("eliminate_allocation type='%d'", |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1010 |
log->identify(tklass->klass())); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1011 |
JVMState* p = alloc->jvms(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1012 |
while (p != NULL) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1013 |
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1014 |
p = p->caller(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1015 |
} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1016 |
log->tail("eliminate_allocation"); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1017 |
} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1018 |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1019 |
process_users_of_allocation(alloc); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1020 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1021 |
#ifndef PRODUCT |
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1022 |
if (PrintEliminateAllocations) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1023 |
if (alloc->is_AllocateArray()) |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1024 |
tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1025 |
else |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1026 |
tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
1027 |
} |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1028 |
#endif |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1029 |
|
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1030 |
return true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1031 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
1032 |
|
17383 | 1033 |
bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) { |
1034 |
// EA should remove all uses of non-escaping boxing node. |
|
1035 |
if (!C->eliminate_boxing() || boxing->proj_out(TypeFunc::Parms) != NULL) { |
|
1036 |
return false; |
|
1037 |
} |
|
1038 |
||
25935
59b08808cb9c
8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943
roland
parents:
25926
diff
changeset
|
1039 |
assert(boxing->result_cast() == NULL, "unexpected boxing node result"); |
59b08808cb9c
8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943
roland
parents:
25926
diff
changeset
|
1040 |
|
17383 | 1041 |
extract_call_projections(boxing); |
1042 |
||
1043 |
const TypeTuple* r = boxing->tf()->range(); |
|
1044 |
assert(r->cnt() > TypeFunc::Parms, "sanity"); |
|
1045 |
const TypeInstPtr* t = r->field_at(TypeFunc::Parms)->isa_instptr(); |
|
1046 |
assert(t != NULL, "sanity"); |
|
1047 |
||
1048 |
CompileLog* log = C->log(); |
|
1049 |
if (log != NULL) { |
|
1050 |
log->head("eliminate_boxing type='%d'", |
|
1051 |
log->identify(t->klass())); |
|
1052 |
JVMState* p = boxing->jvms(); |
|
1053 |
while (p != NULL) { |
|
1054 |
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); |
|
1055 |
p = p->caller(); |
|
1056 |
} |
|
1057 |
log->tail("eliminate_boxing"); |
|
1058 |
} |
|
1059 |
||
1060 |
process_users_of_allocation(boxing); |
|
1061 |
||
1062 |
#ifndef PRODUCT |
|
1063 |
if (PrintEliminateAllocations) { |
|
1064 |
tty->print("++++ Eliminated: %d ", boxing->_idx); |
|
1065 |
boxing->method()->print_short_name(tty); |
|
1066 |
tty->cr(); |
|
1067 |
} |
|
1068 |
#endif |
|
1069 |
||
1070 |
return true; |
|
1071 |
} |
|
1 | 1072 |
|
1073 |
//---------------------------set_eden_pointers------------------------- |
|
1074 |
void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_adr) { |
|
1075 |
if (UseTLAB) { // Private allocation: load from TLS |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1076 |
Node* thread = transform_later(new ThreadLocalNode()); |
1 | 1077 |
int tlab_top_offset = in_bytes(JavaThread::tlab_top_offset()); |
1078 |
int tlab_end_offset = in_bytes(JavaThread::tlab_end_offset()); |
|
1079 |
eden_top_adr = basic_plus_adr(top()/*not oop*/, thread, tlab_top_offset); |
|
1080 |
eden_end_adr = basic_plus_adr(top()/*not oop*/, thread, tlab_end_offset); |
|
1081 |
} else { // Shared allocation: load from globals |
|
1082 |
CollectedHeap* ch = Universe::heap(); |
|
1083 |
address top_adr = (address)ch->top_addr(); |
|
1084 |
address end_adr = (address)ch->end_addr(); |
|
1085 |
eden_top_adr = makecon(TypeRawPtr::make(top_adr)); |
|
1086 |
eden_end_adr = basic_plus_adr(eden_top_adr, end_adr - top_adr); |
|
1087 |
} |
|
1088 |
} |
|
1089 |
||
1090 |
||
1091 |
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) { |
|
1092 |
Node* adr = basic_plus_adr(base, offset); |
|
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
1093 |
const TypePtr* adr_type = adr->bottom_type()->is_ptr(); |
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1094 |
Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt, MemNode::unordered); |
1 | 1095 |
transform_later(value); |
1096 |
return value; |
|
1097 |
} |
|
1098 |
||
1099 |
||
1100 |
Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) { |
|
1101 |
Node* adr = basic_plus_adr(base, offset); |
|
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1102 |
mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt, MemNode::unordered); |
1 | 1103 |
transform_later(mem); |
1104 |
return mem; |
|
1105 |
} |
|
1106 |
||
1107 |
//============================================================================= |
|
1108 |
// |
|
1109 |
// A L L O C A T I O N |
|
1110 |
// |
|
1111 |
// Allocation attempts to be fast in the case of frequent small objects. |
|
1112 |
// It breaks down like this: |
|
1113 |
// |
|
1114 |
// 1) Size in doublewords is computed. This is a constant for objects and |
|
1115 |
// variable for most arrays. Doubleword units are used to avoid size |
|
1116 |
// overflow of huge doubleword arrays. We need doublewords in the end for |
|
1117 |
// rounding. |
|
1118 |
// |
|
1119 |
// 2) Size is checked for being 'too large'. Too-large allocations will go |
|
1120 |
// the slow path into the VM. The slow path can throw any required |
|
1121 |
// exceptions, and does all the special checks for very large arrays. The |
|
1122 |
// size test can constant-fold away for objects. For objects with |
|
1123 |
// finalizers it constant-folds the otherway: you always go slow with |
|
1124 |
// finalizers. |
|
1125 |
// |
|
1126 |
// 3) If NOT using TLABs, this is the contended loop-back point. |
|
1127 |
// Load-Locked the heap top. If using TLABs normal-load the heap top. |
|
1128 |
// |
|
1129 |
// 4) Check that heap top + size*8 < max. If we fail go the slow ` route. |
|
1130 |
// NOTE: "top+size*8" cannot wrap the 4Gig line! Here's why: for largish |
|
1131 |
// "size*8" we always enter the VM, where "largish" is a constant picked small |
|
1132 |
// enough that there's always space between the eden max and 4Gig (old space is |
|
1133 |
// there so it's quite large) and large enough that the cost of entering the VM |
|
1134 |
// is dwarfed by the cost to initialize the space. |
|
1135 |
// |
|
1136 |
// 5) If NOT using TLABs, Store-Conditional the adjusted heap top back |
|
1137 |
// down. If contended, repeat at step 3. If using TLABs normal-store |
|
1138 |
// adjusted heap top back down; there is no contention. |
|
1139 |
// |
|
1140 |
// 6) If !ZeroTLAB then Bulk-clear the object/array. Fill in klass & mark |
|
1141 |
// fields. |
|
1142 |
// |
|
1143 |
// 7) Merge with the slow-path; cast the raw memory pointer to the correct |
|
1144 |
// oop flavor. |
|
1145 |
// |
|
1146 |
//============================================================================= |
|
1147 |
// FastAllocateSizeLimit value is in DOUBLEWORDS. |
|
1148 |
// Allocations bigger than this always go the slow route. |
|
1149 |
// This value must be small enough that allocation attempts that need to |
|
1150 |
// trigger exceptions go the slow route. Also, it must be small enough so |
|
1151 |
// that heap_top + size_in_bytes does not wrap around the 4Gig limit. |
|
1152 |
//=============================================================================j// |
|
1153 |
// %%% Here is an old comment from parseHelper.cpp; is it outdated? |
|
1154 |
// The allocator will coalesce int->oop copies away. See comment in |
|
1155 |
// coalesce.cpp about how this works. It depends critically on the exact |
|
1156 |
// code shape produced here, so if you are changing this code shape |
|
1157 |
// make sure the GC info for the heap-top is correct in and around the |
|
1158 |
// slow-path call. |
|
1159 |
// |
|
1160 |
||
1161 |
void PhaseMacroExpand::expand_allocate_common( |
|
1162 |
AllocateNode* alloc, // allocation node to be expanded |
|
1163 |
Node* length, // array length for an array allocation |
|
1164 |
const TypeFunc* slow_call_type, // Type of slow call |
|
1165 |
address slow_call_address // Address of slow call |
|
1166 |
) |
|
1167 |
{ |
|
1168 |
||
1169 |
Node* ctrl = alloc->in(TypeFunc::Control); |
|
1170 |
Node* mem = alloc->in(TypeFunc::Memory); |
|
1171 |
Node* i_o = alloc->in(TypeFunc::I_O); |
|
1172 |
Node* size_in_bytes = alloc->in(AllocateNode::AllocSize); |
|
1173 |
Node* klass_node = alloc->in(AllocateNode::KlassNode); |
|
1174 |
Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); |
|
1175 |
||
1176 |
assert(ctrl != NULL, "must have control"); |
|
1177 |
// We need a Region and corresponding Phi's to merge the slow-path and fast-path results. |
|
1178 |
// they will not be used if "always_slow" is set |
|
1179 |
enum { slow_result_path = 1, fast_result_path = 2 }; |
|
1180 |
Node *result_region; |
|
1181 |
Node *result_phi_rawmem; |
|
1182 |
Node *result_phi_rawoop; |
|
1183 |
Node *result_phi_i_o; |
|
1184 |
||
1185 |
// The initial slow comparison is a size check, the comparison |
|
1186 |
// we want to do is a BoolTest::gt |
|
1187 |
bool always_slow = false; |
|
1188 |
int tv = _igvn.find_int_con(initial_slow_test, -1); |
|
1189 |
if (tv >= 0) { |
|
1190 |
always_slow = (tv == 1); |
|
1191 |
initial_slow_test = NULL; |
|
1192 |
} else { |
|
1193 |
initial_slow_test = BoolNode::make_predicate(initial_slow_test, &_igvn); |
|
1194 |
} |
|
1195 |
||
2867
69187054225f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
2532
diff
changeset
|
1196 |
if (C->env()->dtrace_alloc_probes() || |
27625 | 1197 |
!UseTLAB && (!Universe::heap()->supports_inline_contig_alloc())) { |
1 | 1198 |
// Force slow-path allocation |
1199 |
always_slow = true; |
|
1200 |
initial_slow_test = NULL; |
|
1201 |
} |
|
1202 |
||
1374
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1203 |
|
1 | 1204 |
enum { too_big_or_final_path = 1, need_gc_path = 2 }; |
1205 |
Node *slow_region = NULL; |
|
1206 |
Node *toobig_false = ctrl; |
|
1207 |
||
1208 |
assert (initial_slow_test == NULL || !always_slow, "arguments must be consistent"); |
|
1209 |
// generate the initial test if necessary |
|
1210 |
if (initial_slow_test != NULL ) { |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1211 |
slow_region = new RegionNode(3); |
1 | 1212 |
|
1213 |
// Now make the initial failure test. Usually a too-big test but |
|
1214 |
// might be a TRUE for finalizers or a fancy class check for |
|
1215 |
// newInstance0. |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1216 |
IfNode *toobig_iff = new IfNode(ctrl, initial_slow_test, PROB_MIN, COUNT_UNKNOWN); |
1 | 1217 |
transform_later(toobig_iff); |
1218 |
// Plug the failing-too-big test into the slow-path region |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1219 |
Node *toobig_true = new IfTrueNode( toobig_iff ); |
1 | 1220 |
transform_later(toobig_true); |
1221 |
slow_region ->init_req( too_big_or_final_path, toobig_true ); |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1222 |
toobig_false = new IfFalseNode( toobig_iff ); |
1 | 1223 |
transform_later(toobig_false); |
1224 |
} else { // No initial test, just fall into next case |
|
1225 |
toobig_false = ctrl; |
|
1226 |
debug_only(slow_region = NodeSentinel); |
|
1227 |
} |
|
1228 |
||
1229 |
Node *slow_mem = mem; // save the current memory state for slow path |
|
1230 |
// generate the fast allocation code unless we know that the initial test will always go slow |
|
1231 |
if (!always_slow) { |
|
2029
4ba79339bc0c
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
1677
diff
changeset
|
1232 |
// Fast path modifies only raw memory. |
4ba79339bc0c
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
1677
diff
changeset
|
1233 |
if (mem->is_MergeMem()) { |
4ba79339bc0c
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
1677
diff
changeset
|
1234 |
mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw); |
4ba79339bc0c
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
1677
diff
changeset
|
1235 |
} |
4ba79339bc0c
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
1677
diff
changeset
|
1236 |
|
1374
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1237 |
Node* eden_top_adr; |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1238 |
Node* eden_end_adr; |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1239 |
|
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1240 |
set_eden_pointers(eden_top_adr, eden_end_adr); |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1241 |
|
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1242 |
// Load Eden::end. Loop invariant and hoisted. |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1243 |
// |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1244 |
// Note: We set the control input on "eden_end" and "old_eden_top" when using |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1245 |
// a TLAB to work around a bug where these values were being moved across |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1246 |
// a safepoint. These are not oops, so they cannot be include in the oop |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1247 |
// map, but they can be changed by a GC. The proper way to fix this would |
1374
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1248 |
// be to set the raw memory state when generating a SafepointNode. However |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1249 |
// this will require extensive changes to the loop optimization in order to |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1250 |
// prevent a degradation of the optimization. |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1251 |
// See comment in memnode.hpp, around line 227 in class LoadPNode. |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1252 |
Node *eden_end = make_load(ctrl, mem, eden_end_adr, 0, TypeRawPtr::BOTTOM, T_ADDRESS); |
4c24294029a9
6711316: Open source the Garbage-First garbage collector
ysr
parents:
371
diff
changeset
|
1253 |
|
1 | 1254 |
// allocate the Region and Phi nodes for the result |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1255 |
result_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1256 |
result_phi_rawmem = new PhiNode(result_region, Type::MEMORY, TypeRawPtr::BOTTOM); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1257 |
result_phi_rawoop = new PhiNode(result_region, TypeRawPtr::BOTTOM); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1258 |
result_phi_i_o = new PhiNode(result_region, Type::ABIO); // I/O is used for Prefetch |
1 | 1259 |
|
1260 |
// We need a Region for the loop-back contended case. |
|
1261 |
enum { fall_in_path = 1, contended_loopback_path = 2 }; |
|
1262 |
Node *contended_region; |
|
1263 |
Node *contended_phi_rawmem; |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1264 |
if (UseTLAB) { |
1 | 1265 |
contended_region = toobig_false; |
1266 |
contended_phi_rawmem = mem; |
|
1267 |
} else { |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1268 |
contended_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1269 |
contended_phi_rawmem = new PhiNode(contended_region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1 | 1270 |
// Now handle the passing-too-big test. We fall into the contended |
1271 |
// loop-back merge point. |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1272 |
contended_region ->init_req(fall_in_path, toobig_false); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1273 |
contended_phi_rawmem->init_req(fall_in_path, mem); |
1 | 1274 |
transform_later(contended_region); |
1275 |
transform_later(contended_phi_rawmem); |
|
1276 |
} |
|
1277 |
||
1278 |
// Load(-locked) the heap top. |
|
1279 |
// See note above concerning the control input when using a TLAB |
|
1280 |
Node *old_eden_top = UseTLAB |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1281 |
? new LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered) |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1282 |
: new LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire); |
1 | 1283 |
|
1284 |
transform_later(old_eden_top); |
|
1285 |
// Add to heap top to get a new heap top |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1286 |
Node *new_eden_top = new AddPNode(top(), old_eden_top, size_in_bytes); |
1 | 1287 |
transform_later(new_eden_top); |
1288 |
// Check for needing a GC; compare against heap end |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1289 |
Node *needgc_cmp = new CmpPNode(new_eden_top, eden_end); |
1 | 1290 |
transform_later(needgc_cmp); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1291 |
Node *needgc_bol = new BoolNode(needgc_cmp, BoolTest::ge); |
1 | 1292 |
transform_later(needgc_bol); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1293 |
IfNode *needgc_iff = new IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN); |
1 | 1294 |
transform_later(needgc_iff); |
1295 |
||
1296 |
// Plug the failing-heap-space-need-gc test into the slow-path region |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1297 |
Node *needgc_true = new IfTrueNode(needgc_iff); |
1 | 1298 |
transform_later(needgc_true); |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1299 |
if (initial_slow_test) { |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1300 |
slow_region->init_req(need_gc_path, needgc_true); |
1 | 1301 |
// This completes all paths into the slow merge point |
1302 |
transform_later(slow_region); |
|
1303 |
} else { // No initial slow path needed! |
|
1304 |
// Just fall from the need-GC path straight into the VM call. |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1305 |
slow_region = needgc_true; |
1 | 1306 |
} |
1307 |
// No need for a GC. Setup for the Store-Conditional |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1308 |
Node *needgc_false = new IfFalseNode(needgc_iff); |
1 | 1309 |
transform_later(needgc_false); |
1310 |
||
1311 |
// Grab regular I/O before optional prefetch may change it. |
|
1312 |
// Slow-path does no I/O so just set it to the original I/O. |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1313 |
result_phi_i_o->init_req(slow_result_path, i_o); |
1 | 1314 |
|
1315 |
i_o = prefetch_allocation(i_o, needgc_false, contended_phi_rawmem, |
|
1316 |
old_eden_top, new_eden_top, length); |
|
1317 |
||
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1318 |
// Name successful fast-path variables |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1319 |
Node* fast_oop = old_eden_top; |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1320 |
Node* fast_oop_ctrl; |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1321 |
Node* fast_oop_rawmem; |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1322 |
|
1 | 1323 |
// Store (-conditional) the modified eden top back down. |
1324 |
// StorePConditional produces flags for a test PLUS a modified raw |
|
1325 |
// memory state. |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1326 |
if (UseTLAB) { |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1327 |
Node* store_eden_top = |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1328 |
new StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr, |
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1329 |
TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered); |
1 | 1330 |
transform_later(store_eden_top); |
1331 |
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1332 |
fast_oop_rawmem = store_eden_top; |
1 | 1333 |
} else { |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1334 |
Node* store_eden_top = |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1335 |
new StorePConditionalNode(needgc_false, contended_phi_rawmem, eden_top_adr, |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1336 |
new_eden_top, fast_oop/*old_eden_top*/); |
1 | 1337 |
transform_later(store_eden_top); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1338 |
Node *contention_check = new BoolNode(store_eden_top, BoolTest::ne); |
1 | 1339 |
transform_later(contention_check); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1340 |
store_eden_top = new SCMemProjNode(store_eden_top); |
1 | 1341 |
transform_later(store_eden_top); |
1342 |
||
1343 |
// If not using TLABs, check to see if there was contention. |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1344 |
IfNode *contention_iff = new IfNode (needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN); |
1 | 1345 |
transform_later(contention_iff); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1346 |
Node *contention_true = new IfTrueNode(contention_iff); |
1 | 1347 |
transform_later(contention_true); |
1348 |
// If contention, loopback and try again. |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1349 |
contended_region->init_req(contended_loopback_path, contention_true); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1350 |
contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top); |
1 | 1351 |
|
1352 |
// Fast-path succeeded with no contention! |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1353 |
Node *contention_false = new IfFalseNode(contention_iff); |
1 | 1354 |
transform_later(contention_false); |
1355 |
fast_oop_ctrl = contention_false; |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1356 |
|
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1357 |
// Bump total allocated bytes for this thread |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1358 |
Node* thread = new ThreadLocalNode(); |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1359 |
transform_later(thread); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1360 |
Node* alloc_bytes_adr = basic_plus_adr(top()/*not oop*/, thread, |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1361 |
in_bytes(JavaThread::allocated_bytes_offset())); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1362 |
Node* alloc_bytes = make_load(fast_oop_ctrl, store_eden_top, alloc_bytes_adr, |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1363 |
0, TypeLong::LONG, T_LONG); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1364 |
#ifdef _LP64 |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1365 |
Node* alloc_size = size_in_bytes; |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1366 |
#else |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1367 |
Node* alloc_size = new ConvI2LNode(size_in_bytes); |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1368 |
transform_later(alloc_size); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1369 |
#endif |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1370 |
Node* new_alloc_bytes = new AddLNode(alloc_bytes, alloc_size); |
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1371 |
transform_later(new_alloc_bytes); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1372 |
fast_oop_rawmem = make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr, |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1373 |
0, new_alloc_bytes, T_LONG); |
1 | 1374 |
} |
1375 |
||
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1376 |
InitializeNode* init = alloc->initialization(); |
1 | 1377 |
fast_oop_rawmem = initialize_object(alloc, |
1378 |
fast_oop_ctrl, fast_oop_rawmem, fast_oop, |
|
1379 |
klass_node, length, size_in_bytes); |
|
1380 |
||
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1381 |
// If initialization is performed by an array copy, any required |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1382 |
// MemBarStoreStore was already added. If the object does not |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1383 |
// escape no need for a MemBarStoreStore. Otherwise we need a |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1384 |
// MemBarStoreStore so that stores that initialize this object |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1385 |
// can't be reordered with a subsequent store that makes this |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1386 |
// object accessible by other threads. |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1387 |
if (init == NULL || (!init->is_complete_with_arraycopy() && !init->does_not_escape())) { |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1388 |
if (init == NULL || init->req() < InitializeNode::RawStores) { |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1389 |
// No InitializeNode or no stores captured by zeroing |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1390 |
// elimination. Simply add the MemBarStoreStore after object |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1391 |
// initialization. |
15874
57f16a8b609f
8009460: C2compiler crash in machnode::in_regmask(unsigned int)
roland
parents:
15242
diff
changeset
|
1392 |
MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1393 |
transform_later(mb); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1394 |
|
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1395 |
mb->init_req(TypeFunc::Memory, fast_oop_rawmem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1396 |
mb->init_req(TypeFunc::Control, fast_oop_ctrl); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1397 |
fast_oop_ctrl = new ProjNode(mb,TypeFunc::Control); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1398 |
transform_later(fast_oop_ctrl); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1399 |
fast_oop_rawmem = new ProjNode(mb,TypeFunc::Memory); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1400 |
transform_later(fast_oop_rawmem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1401 |
} else { |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1402 |
// Add the MemBarStoreStore after the InitializeNode so that |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1403 |
// all stores performing the initialization that were moved |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1404 |
// before the InitializeNode happen before the storestore |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1405 |
// barrier. |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1406 |
|
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1407 |
Node* init_ctrl = init->proj_out(TypeFunc::Control); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1408 |
Node* init_mem = init->proj_out(TypeFunc::Memory); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1409 |
|
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1410 |
MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1411 |
transform_later(mb); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1412 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1413 |
Node* ctrl = new ProjNode(init,TypeFunc::Control); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1414 |
transform_later(ctrl); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1415 |
Node* mem = new ProjNode(init,TypeFunc::Memory); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1416 |
transform_later(mem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1417 |
|
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1418 |
// The MemBarStoreStore depends on control and memory coming |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1419 |
// from the InitializeNode |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1420 |
mb->init_req(TypeFunc::Memory, mem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1421 |
mb->init_req(TypeFunc::Control, ctrl); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1422 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1423 |
ctrl = new ProjNode(mb,TypeFunc::Control); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1424 |
transform_later(ctrl); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1425 |
mem = new ProjNode(mb,TypeFunc::Memory); |
11431
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1426 |
transform_later(mem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1427 |
|
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1428 |
// All nodes that depended on the InitializeNode for control |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1429 |
// and memory must now depend on the MemBarNode that itself |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1430 |
// depends on the InitializeNode |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1431 |
_igvn.replace_node(init_ctrl, ctrl); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1432 |
_igvn.replace_node(init_mem, mem); |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1433 |
} |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1434 |
} |
5ca3a19e559a
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
11430
diff
changeset
|
1435 |
|
2867
69187054225f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
2532
diff
changeset
|
1436 |
if (C->env()->dtrace_extended_probes()) { |
1 | 1437 |
// Slow-path call |
1438 |
int size = TypeFunc::Parms + 2; |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1439 |
CallLeafNode *call = new CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(), |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1440 |
CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc_base), |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1441 |
"dtrace_object_alloc", |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1442 |
TypeRawPtr::BOTTOM); |
1 | 1443 |
|
1444 |
// Get base of thread-local storage area |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1445 |
Node* thread = new ThreadLocalNode(); |
1 | 1446 |
transform_later(thread); |
1447 |
||
1448 |
call->init_req(TypeFunc::Parms+0, thread); |
|
1449 |
call->init_req(TypeFunc::Parms+1, fast_oop); |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1450 |
call->init_req(TypeFunc::Control, fast_oop_ctrl); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1451 |
call->init_req(TypeFunc::I_O , top()); // does no i/o |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1452 |
call->init_req(TypeFunc::Memory , fast_oop_rawmem); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1453 |
call->init_req(TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr)); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1454 |
call->init_req(TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr)); |
1 | 1455 |
transform_later(call); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1456 |
fast_oop_ctrl = new ProjNode(call,TypeFunc::Control); |
1 | 1457 |
transform_later(fast_oop_ctrl); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1458 |
fast_oop_rawmem = new ProjNode(call,TypeFunc::Memory); |
1 | 1459 |
transform_later(fast_oop_rawmem); |
1460 |
} |
|
1461 |
||
1462 |
// Plug in the successful fast-path into the result merge point |
|
7724
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1463 |
result_region ->init_req(fast_result_path, fast_oop_ctrl); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1464 |
result_phi_rawoop->init_req(fast_result_path, fast_oop); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1465 |
result_phi_i_o ->init_req(fast_result_path, i_o); |
a92d706dbdd5
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
7397
diff
changeset
|
1466 |
result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem); |
1 | 1467 |
} else { |
1468 |
slow_region = ctrl; |
|
11435 | 1469 |
result_phi_i_o = i_o; // Rename it to use in the following code. |
1 | 1470 |
} |
1471 |
||
1472 |
// Generate slow-path call |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1473 |
CallNode *call = new CallStaticJavaNode(slow_call_type, slow_call_address, |
13895
f6dfe4123709
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
13728
diff
changeset
|
1474 |
OptoRuntime::stub_name(slow_call_address), |
f6dfe4123709
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
13728
diff
changeset
|
1475 |
alloc->jvms()->bci(), |
f6dfe4123709
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
13728
diff
changeset
|
1476 |
TypePtr::BOTTOM); |
1 | 1477 |
call->init_req( TypeFunc::Control, slow_region ); |
1478 |
call->init_req( TypeFunc::I_O , top() ) ; // does no i/o |
|
1479 |
call->init_req( TypeFunc::Memory , slow_mem ); // may gc ptrs |
|
1480 |
call->init_req( TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr) ); |
|
1481 |
call->init_req( TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr) ); |
|
1482 |
||
1483 |
call->init_req(TypeFunc::Parms+0, klass_node); |
|
1484 |
if (length != NULL) { |
|
1485 |
call->init_req(TypeFunc::Parms+1, length); |
|
1486 |
} |
|
1487 |
||
1488 |
// Copy debug information and adjust JVMState information, then replace |
|
1489 |
// allocate node with the call |
|
1490 |
copy_call_debug_info((CallNode *) alloc, call); |
|
1491 |
if (!always_slow) { |
|
1492 |
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. |
|
11435 | 1493 |
} else { |
1494 |
// Hook i_o projection to avoid its elimination during allocation |
|
1495 |
// replacement (when only a slow call is generated). |
|
1496 |
call->set_req(TypeFunc::I_O, result_phi_i_o); |
|
1 | 1497 |
} |
5901
c046f8e9c52b
6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents:
5889
diff
changeset
|
1498 |
_igvn.replace_node(alloc, call); |
1 | 1499 |
transform_later(call); |
1500 |
||
1501 |
// Identify the output projections from the allocate node and |
|
1502 |
// adjust any references to them. |
|
1503 |
// The control and io projections look like: |
|
1504 |
// |
|
1505 |
// v---Proj(ctrl) <-----+ v---CatchProj(ctrl) |
|
1506 |
// Allocate Catch |
|
1507 |
// ^---Proj(io) <-------+ ^---CatchProj(io) |
|
1508 |
// |
|
1509 |
// We are interested in the CatchProj nodes. |
|
1510 |
// |
|
1511 |
extract_call_projections(call); |
|
1512 |
||
11435 | 1513 |
// An allocate node has separate memory projections for the uses on |
1514 |
// the control and i_o paths. Replace the control memory projection with |
|
1515 |
// result_phi_rawmem (unless we are only generating a slow call when |
|
1516 |
// both memory projections are combined) |
|
1 | 1517 |
if (!always_slow && _memproj_fallthrough != NULL) { |
1518 |
for (DUIterator_Fast imax, i = _memproj_fallthrough->fast_outs(imax); i < imax; i++) { |
|
1519 |
Node *use = _memproj_fallthrough->fast_out(i); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1520 |
_igvn.rehash_node_delayed(use); |
1 | 1521 |
imax -= replace_input(use, _memproj_fallthrough, result_phi_rawmem); |
1522 |
// back up iterator |
|
1523 |
--i; |
|
1524 |
} |
|
1525 |
} |
|
11435 | 1526 |
// Now change uses of _memproj_catchall to use _memproj_fallthrough and delete |
1527 |
// _memproj_catchall so we end up with a call that has only 1 memory projection. |
|
1 | 1528 |
if (_memproj_catchall != NULL ) { |
1529 |
if (_memproj_fallthrough == NULL) { |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1530 |
_memproj_fallthrough = new ProjNode(call, TypeFunc::Memory); |
1 | 1531 |
transform_later(_memproj_fallthrough); |
1532 |
} |
|
1533 |
for (DUIterator_Fast imax, i = _memproj_catchall->fast_outs(imax); i < imax; i++) { |
|
1534 |
Node *use = _memproj_catchall->fast_out(i); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1535 |
_igvn.rehash_node_delayed(use); |
1 | 1536 |
imax -= replace_input(use, _memproj_catchall, _memproj_fallthrough); |
1537 |
// back up iterator |
|
1538 |
--i; |
|
1539 |
} |
|
11435 | 1540 |
assert(_memproj_catchall->outcnt() == 0, "all uses must be deleted"); |
1541 |
_igvn.remove_dead_node(_memproj_catchall); |
|
1 | 1542 |
} |
1543 |
||
11435 | 1544 |
// An allocate node has separate i_o projections for the uses on the control |
1545 |
// and i_o paths. Always replace the control i_o projection with result i_o |
|
1546 |
// otherwise incoming i_o become dead when only a slow call is generated |
|
1547 |
// (it is different from memory projections where both projections are |
|
1548 |
// combined in such case). |
|
1549 |
if (_ioproj_fallthrough != NULL) { |
|
1 | 1550 |
for (DUIterator_Fast imax, i = _ioproj_fallthrough->fast_outs(imax); i < imax; i++) { |
1551 |
Node *use = _ioproj_fallthrough->fast_out(i); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1552 |
_igvn.rehash_node_delayed(use); |
1 | 1553 |
imax -= replace_input(use, _ioproj_fallthrough, result_phi_i_o); |
1554 |
// back up iterator |
|
1555 |
--i; |
|
1556 |
} |
|
1557 |
} |
|
11435 | 1558 |
// Now change uses of _ioproj_catchall to use _ioproj_fallthrough and delete |
1559 |
// _ioproj_catchall so we end up with a call that has only 1 i_o projection. |
|
1 | 1560 |
if (_ioproj_catchall != NULL ) { |
11435 | 1561 |
if (_ioproj_fallthrough == NULL) { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1562 |
_ioproj_fallthrough = new ProjNode(call, TypeFunc::I_O); |
11435 | 1563 |
transform_later(_ioproj_fallthrough); |
1564 |
} |
|
1 | 1565 |
for (DUIterator_Fast imax, i = _ioproj_catchall->fast_outs(imax); i < imax; i++) { |
1566 |
Node *use = _ioproj_catchall->fast_out(i); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1567 |
_igvn.rehash_node_delayed(use); |
1 | 1568 |
imax -= replace_input(use, _ioproj_catchall, _ioproj_fallthrough); |
1569 |
// back up iterator |
|
1570 |
--i; |
|
1571 |
} |
|
11435 | 1572 |
assert(_ioproj_catchall->outcnt() == 0, "all uses must be deleted"); |
1573 |
_igvn.remove_dead_node(_ioproj_catchall); |
|
1 | 1574 |
} |
1575 |
||
1576 |
// if we generated only a slow call, we are done |
|
11435 | 1577 |
if (always_slow) { |
1578 |
// Now we can unhook i_o. |
|
11437 | 1579 |
if (result_phi_i_o->outcnt() > 1) { |
1580 |
call->set_req(TypeFunc::I_O, top()); |
|
1581 |
} else { |
|
1582 |
assert(result_phi_i_o->unique_ctrl_out() == call, ""); |
|
1583 |
// Case of new array with negative size known during compilation. |
|
1584 |
// AllocateArrayNode::Ideal() optimization disconnect unreachable |
|
1585 |
// following code since call to runtime will throw exception. |
|
1586 |
// As result there will be no users of i_o after the call. |
|
1587 |
// Leave i_o attached to this call to avoid problems in preceding graph. |
|
1588 |
} |
|
1 | 1589 |
return; |
11435 | 1590 |
} |
1 | 1591 |
|
1592 |
||
1593 |
if (_fallthroughcatchproj != NULL) { |
|
1594 |
ctrl = _fallthroughcatchproj->clone(); |
|
1595 |
transform_later(ctrl); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
1596 |
_igvn.replace_node(_fallthroughcatchproj, result_region); |
1 | 1597 |
} else { |
1598 |
ctrl = top(); |
|
1599 |
} |
|
1600 |
Node *slow_result; |
|
1601 |
if (_resproj == NULL) { |
|
1602 |
// no uses of the allocation result |
|
1603 |
slow_result = top(); |
|
1604 |
} else { |
|
1605 |
slow_result = _resproj->clone(); |
|
1606 |
transform_later(slow_result); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
1607 |
_igvn.replace_node(_resproj, result_phi_rawoop); |
1 | 1608 |
} |
1609 |
||
1610 |
// Plug slow-path into result merge point |
|
1611 |
result_region ->init_req( slow_result_path, ctrl ); |
|
1612 |
result_phi_rawoop->init_req( slow_result_path, slow_result); |
|
1613 |
result_phi_rawmem->init_req( slow_result_path, _memproj_fallthrough ); |
|
1614 |
transform_later(result_region); |
|
1615 |
transform_later(result_phi_rawoop); |
|
1616 |
transform_later(result_phi_rawmem); |
|
1617 |
transform_later(result_phi_i_o); |
|
1618 |
// This completes all paths into the result merge point |
|
1619 |
} |
|
1620 |
||
1621 |
||
1622 |
// Helper for PhaseMacroExpand::expand_allocate_common. |
|
1623 |
// Initializes the newly-allocated storage. |
|
1624 |
Node* |
|
1625 |
PhaseMacroExpand::initialize_object(AllocateNode* alloc, |
|
1626 |
Node* control, Node* rawmem, Node* object, |
|
1627 |
Node* klass_node, Node* length, |
|
1628 |
Node* size_in_bytes) { |
|
1629 |
InitializeNode* init = alloc->initialization(); |
|
1630 |
// Store the klass & mark bits |
|
1631 |
Node* mark_node = NULL; |
|
1632 |
// For now only enable fast locking for non-array types |
|
1633 |
if (UseBiasedLocking && (length == NULL)) { |
|
11430
718fc06da49a
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
11191
diff
changeset
|
1634 |
mark_node = make_load(control, rawmem, klass_node, in_bytes(Klass::prototype_header_offset()), TypeRawPtr::BOTTOM, T_ADDRESS); |
1 | 1635 |
} else { |
1636 |
mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype())); |
|
1637 |
} |
|
1638 |
rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS); |
|
360
21d113ecbf6a
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
246
diff
changeset
|
1639 |
|
13728
882756847a04
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
13195
diff
changeset
|
1640 |
rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_METADATA); |
1 | 1641 |
int header_size = alloc->minimum_header_size(); // conservatively small |
1642 |
||
1643 |
// Array length |
|
1644 |
if (length != NULL) { // Arrays need length field |
|
1645 |
rawmem = make_store(control, rawmem, object, arrayOopDesc::length_offset_in_bytes(), length, T_INT); |
|
1646 |
// conservatively small header size: |
|
360
21d113ecbf6a
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
246
diff
changeset
|
1647 |
header_size = arrayOopDesc::base_offset_in_bytes(T_BYTE); |
1 | 1648 |
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); |
1649 |
if (k->is_array_klass()) // we know the exact header size in most cases: |
|
1650 |
header_size = Klass::layout_helper_header_size(k->layout_helper()); |
|
1651 |
} |
|
1652 |
||
1653 |
// Clear the object body, if necessary. |
|
1654 |
if (init == NULL) { |
|
1655 |
// The init has somehow disappeared; be cautious and clear everything. |
|
1656 |
// |
|
1657 |
// This can happen if a node is allocated but an uncommon trap occurs |
|
1658 |
// immediately. In this case, the Initialize gets associated with the |
|
1659 |
// trap, and may be placed in a different (outer) loop, if the Allocate |
|
1660 |
// is in a loop. If (this is rare) the inner loop gets unrolled, then |
|
1661 |
// there can be two Allocates to one Initialize. The answer in all these |
|
1662 |
// edge cases is safety first. It is always safe to clear immediately |
|
1663 |
// within an Allocate, and then (maybe or maybe not) clear some more later. |
|
1664 |
if (!ZeroTLAB) |
|
1665 |
rawmem = ClearArrayNode::clear_memory(control, rawmem, object, |
|
1666 |
header_size, size_in_bytes, |
|
1667 |
&_igvn); |
|
1668 |
} else { |
|
1669 |
if (!init->is_complete()) { |
|
1670 |
// Try to win by zeroing only what the init does not store. |
|
1671 |
// We can also try to do some peephole optimizations, |
|
1672 |
// such as combining some adjacent subword stores. |
|
1673 |
rawmem = init->complete_stores(control, rawmem, object, |
|
1674 |
header_size, size_in_bytes, &_igvn); |
|
1675 |
} |
|
1676 |
// We have no more use for this link, since the AllocateNode goes away: |
|
1677 |
init->set_req(InitializeNode::RawAddress, top()); |
|
1678 |
// (If we keep the link, it just confuses the register allocator, |
|
1679 |
// who thinks he sees a real use of the address by the membar.) |
|
1680 |
} |
|
1681 |
||
1682 |
return rawmem; |
|
1683 |
} |
|
1684 |
||
1685 |
// Generate prefetch instructions for next allocations. |
|
1686 |
Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, |
|
1687 |
Node*& contended_phi_rawmem, |
|
1688 |
Node* old_eden_top, Node* new_eden_top, |
|
1689 |
Node* length) { |
|
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1690 |
enum { fall_in_path = 1, pf_path = 2 }; |
1 | 1691 |
if( UseTLAB && AllocatePrefetchStyle == 2 ) { |
1692 |
// Generate prefetch allocation with watermark check. |
|
1693 |
// As an allocation hits the watermark, we will prefetch starting |
|
1694 |
// at a "distance" away from watermark. |
|
1695 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1696 |
Node *pf_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1697 |
Node *pf_phi_rawmem = new PhiNode( pf_region, Type::MEMORY, |
1 | 1698 |
TypeRawPtr::BOTTOM ); |
1699 |
// I/O is used for Prefetch |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1700 |
Node *pf_phi_abio = new PhiNode( pf_region, Type::ABIO ); |
1 | 1701 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1702 |
Node *thread = new ThreadLocalNode(); |
1 | 1703 |
transform_later(thread); |
1704 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1705 |
Node *eden_pf_adr = new AddPNode( top()/*not oop*/, thread, |
1 | 1706 |
_igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset())) ); |
1707 |
transform_later(eden_pf_adr); |
|
1708 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1709 |
Node *old_pf_wm = new LoadPNode(needgc_false, |
1 | 1710 |
contended_phi_rawmem, eden_pf_adr, |
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1711 |
TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, |
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1712 |
MemNode::unordered); |
1 | 1713 |
transform_later(old_pf_wm); |
1714 |
||
1715 |
// check against new_eden_top |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1716 |
Node *need_pf_cmp = new CmpPNode( new_eden_top, old_pf_wm ); |
1 | 1717 |
transform_later(need_pf_cmp); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1718 |
Node *need_pf_bol = new BoolNode( need_pf_cmp, BoolTest::ge ); |
1 | 1719 |
transform_later(need_pf_bol); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1720 |
IfNode *need_pf_iff = new IfNode( needgc_false, need_pf_bol, |
1 | 1721 |
PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN ); |
1722 |
transform_later(need_pf_iff); |
|
1723 |
||
1724 |
// true node, add prefetchdistance |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1725 |
Node *need_pf_true = new IfTrueNode( need_pf_iff ); |
1 | 1726 |
transform_later(need_pf_true); |
1727 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1728 |
Node *need_pf_false = new IfFalseNode( need_pf_iff ); |
1 | 1729 |
transform_later(need_pf_false); |
1730 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1731 |
Node *new_pf_wmt = new AddPNode( top(), old_pf_wm, |
1 | 1732 |
_igvn.MakeConX(AllocatePrefetchDistance) ); |
1733 |
transform_later(new_pf_wmt ); |
|
1734 |
new_pf_wmt->set_req(0, need_pf_true); |
|
1735 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1736 |
Node *store_new_wmt = new StorePNode(need_pf_true, |
1 | 1737 |
contended_phi_rawmem, eden_pf_adr, |
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1738 |
TypeRawPtr::BOTTOM, new_pf_wmt, |
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
19979
diff
changeset
|
1739 |
MemNode::unordered); |
1 | 1740 |
transform_later(store_new_wmt); |
1741 |
||
1742 |
// adding prefetches |
|
1743 |
pf_phi_abio->init_req( fall_in_path, i_o ); |
|
1744 |
||
1745 |
Node *prefetch_adr; |
|
1746 |
Node *prefetch; |
|
1747 |
uint lines = AllocatePrefetchDistance / AllocatePrefetchStepSize; |
|
1748 |
uint step_size = AllocatePrefetchStepSize; |
|
1749 |
uint distance = 0; |
|
1750 |
||
1751 |
for ( uint i = 0; i < lines; i++ ) { |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1752 |
prefetch_adr = new AddPNode( old_pf_wm, new_pf_wmt, |
1 | 1753 |
_igvn.MakeConX(distance) ); |
1754 |
transform_later(prefetch_adr); |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1755 |
prefetch = new PrefetchAllocationNode( i_o, prefetch_adr ); |
1 | 1756 |
transform_later(prefetch); |
1757 |
distance += step_size; |
|
1758 |
i_o = prefetch; |
|
1759 |
} |
|
1760 |
pf_phi_abio->set_req( pf_path, i_o ); |
|
1761 |
||
1762 |
pf_region->init_req( fall_in_path, need_pf_false ); |
|
1763 |
pf_region->init_req( pf_path, need_pf_true ); |
|
1764 |
||
1765 |
pf_phi_rawmem->init_req( fall_in_path, contended_phi_rawmem ); |
|
1766 |
pf_phi_rawmem->init_req( pf_path, store_new_wmt ); |
|
1767 |
||
1768 |
transform_later(pf_region); |
|
1769 |
transform_later(pf_phi_rawmem); |
|
1770 |
transform_later(pf_phi_abio); |
|
1771 |
||
1772 |
needgc_false = pf_region; |
|
1773 |
contended_phi_rawmem = pf_phi_rawmem; |
|
1774 |
i_o = pf_phi_abio; |
|
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1775 |
} else if( UseTLAB && AllocatePrefetchStyle == 3 ) { |
10267 | 1776 |
// Insert a prefetch for each allocation. |
1777 |
// This code is used for Sparc with BIS. |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1778 |
Node *pf_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1779 |
Node *pf_phi_rawmem = new PhiNode( pf_region, Type::MEMORY, |
13895
f6dfe4123709
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
13728
diff
changeset
|
1780 |
TypeRawPtr::BOTTOM ); |
25913
81dbc151e91c
8040213: C2 does not put all modified nodes on IGVN worklist
thartmann
parents:
24923
diff
changeset
|
1781 |
transform_later(pf_region); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1782 |
|
10267 | 1783 |
// Generate several prefetch instructions. |
1784 |
uint lines = (length != NULL) ? AllocatePrefetchLines : AllocateInstancePrefetchLines; |
|
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1785 |
uint step_size = AllocatePrefetchStepSize; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1786 |
uint distance = AllocatePrefetchDistance; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1787 |
|
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1788 |
// Next cache address. |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1789 |
Node *cache_adr = new AddPNode(old_eden_top, old_eden_top, |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1790 |
_igvn.MakeConX(distance)); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1791 |
transform_later(cache_adr); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1792 |
cache_adr = new CastP2XNode(needgc_false, cache_adr); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1793 |
transform_later(cache_adr); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1794 |
Node* mask = _igvn.MakeConX(~(intptr_t)(step_size-1)); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1795 |
cache_adr = new AndXNode(cache_adr, mask); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1796 |
transform_later(cache_adr); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1797 |
cache_adr = new CastX2PNode(cache_adr); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1798 |
transform_later(cache_adr); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1799 |
|
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1800 |
// Prefetch |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1801 |
Node *prefetch = new PrefetchAllocationNode( contended_phi_rawmem, cache_adr ); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1802 |
prefetch->set_req(0, needgc_false); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1803 |
transform_later(prefetch); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1804 |
contended_phi_rawmem = prefetch; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1805 |
Node *prefetch_adr; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1806 |
distance = step_size; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1807 |
for ( uint i = 1; i < lines; i++ ) { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1808 |
prefetch_adr = new AddPNode( cache_adr, cache_adr, |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1809 |
_igvn.MakeConX(distance) ); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1810 |
transform_later(prefetch_adr); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1811 |
prefetch = new PrefetchAllocationNode( contended_phi_rawmem, prefetch_adr ); |
5251
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1812 |
transform_later(prefetch); |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1813 |
distance += step_size; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1814 |
contended_phi_rawmem = prefetch; |
f86f7a86d761
6940726: Use BIS instruction for allocation prefetch on Sparc
kvn
parents:
4470
diff
changeset
|
1815 |
} |
1 | 1816 |
} else if( AllocatePrefetchStyle > 0 ) { |
1817 |
// Insert a prefetch for each allocation only on the fast-path |
|
1818 |
Node *prefetch_adr; |
|
1819 |
Node *prefetch; |
|
10267 | 1820 |
// Generate several prefetch instructions. |
1821 |
uint lines = (length != NULL) ? AllocatePrefetchLines : AllocateInstancePrefetchLines; |
|
1 | 1822 |
uint step_size = AllocatePrefetchStepSize; |
1823 |
uint distance = AllocatePrefetchDistance; |
|
1824 |
for ( uint i = 0; i < lines; i++ ) { |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1825 |
prefetch_adr = new AddPNode( old_eden_top, new_eden_top, |
1 | 1826 |
_igvn.MakeConX(distance) ); |
1827 |
transform_later(prefetch_adr); |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
1828 |
prefetch = new PrefetchAllocationNode( i_o, prefetch_adr ); |
1 | 1829 |
// Do not let it float too high, since if eden_top == eden_end, |
1830 |
// both might be null. |
|
1831 |
if( i == 0 ) { // Set control for first prefetch, next follows it |
|
1832 |
prefetch->init_req(0, needgc_false); |
|
1833 |
} |
|
1834 |
transform_later(prefetch); |
|
1835 |
distance += step_size; |
|
1836 |
i_o = prefetch; |
|
1837 |
} |
|
1838 |
} |
|
1839 |
return i_o; |
|
1840 |
} |
|
1841 |
||
1842 |
||
1843 |
void PhaseMacroExpand::expand_allocate(AllocateNode *alloc) { |
|
1844 |
expand_allocate_common(alloc, NULL, |
|
1845 |
OptoRuntime::new_instance_Type(), |
|
1846 |
OptoRuntime::new_instance_Java()); |
|
1847 |
} |
|
1848 |
||
1849 |
void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { |
|
1850 |
Node* length = alloc->in(AllocateNode::ALength); |
|
10566
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1851 |
InitializeNode* init = alloc->initialization(); |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1852 |
Node* klass_node = alloc->in(AllocateNode::KlassNode); |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1853 |
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1854 |
address slow_call_address; // Address of slow call |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1855 |
if (init != NULL && init->is_complete_with_arraycopy() && |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1856 |
k->is_type_array_klass()) { |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1857 |
// Don't zero type array during slow allocation in VM since |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1858 |
// it will be initialized later by arraycopy in compiled code. |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1859 |
slow_call_address = OptoRuntime::new_array_nozero_Java(); |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1860 |
} else { |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1861 |
slow_call_address = OptoRuntime::new_array_Java(); |
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1862 |
} |
1 | 1863 |
expand_allocate_common(alloc, length, |
1864 |
OptoRuntime::new_array_Type(), |
|
10566
630c177ec580
7081933: Use zeroing elimination optimization for large array
kvn
parents:
10267
diff
changeset
|
1865 |
slow_call_address); |
1 | 1866 |
} |
1867 |
||
11445 | 1868 |
//-------------------mark_eliminated_box---------------------------------- |
1869 |
// |
|
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1870 |
// During EA obj may point to several objects but after few ideal graph |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1871 |
// transformations (CCP) it may point to only one non escaping object |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1872 |
// (but still using phi), corresponding locks and unlocks will be marked |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1873 |
// for elimination. Later obj could be replaced with a new node (new phi) |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1874 |
// and which does not have escape information. And later after some graph |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1875 |
// reshape other locks and unlocks (which were not marked for elimination |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1876 |
// before) are connected to this new obj (phi) but they still will not be |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1877 |
// marked for elimination since new obj has no escape information. |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1878 |
// Mark all associated (same box and obj) lock and unlock nodes for |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1879 |
// elimination if some of them marked already. |
11445 | 1880 |
void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { |
11460 | 1881 |
if (oldbox->as_BoxLock()->is_eliminated()) |
1882 |
return; // This BoxLock node was processed already. |
|
11445 | 1883 |
|
11460 | 1884 |
// New implementation (EliminateNestedLocks) has separate BoxLock |
1885 |
// node for each locked region so mark all associated locks/unlocks as |
|
1886 |
// eliminated even if different objects are referenced in one locked region |
|
1887 |
// (for example, OSR compilation of nested loop inside locked scope). |
|
1888 |
if (EliminateNestedLocks || |
|
11445 | 1889 |
oldbox->as_BoxLock()->is_simple_lock_region(NULL, obj)) { |
1890 |
// Box is used only in one lock region. Mark this box as eliminated. |
|
1891 |
_igvn.hash_delete(oldbox); |
|
1892 |
oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value |
|
1893 |
_igvn.hash_insert(oldbox); |
|
1894 |
||
1895 |
for (uint i = 0; i < oldbox->outcnt(); i++) { |
|
1896 |
Node* u = oldbox->raw_out(i); |
|
1897 |
if (u->is_AbstractLock() && !u->as_AbstractLock()->is_non_esc_obj()) { |
|
1898 |
AbstractLockNode* alock = u->as_AbstractLock(); |
|
1899 |
// Check lock's box since box could be referenced by Lock's debug info. |
|
1900 |
if (alock->box_node() == oldbox) { |
|
1901 |
// Mark eliminated all related locks and unlocks. |
|
1902 |
alock->set_non_esc_obj(); |
|
1903 |
} |
|
1904 |
} |
|
1905 |
} |
|
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1906 |
return; |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
1907 |
} |
11445 | 1908 |
|
1909 |
// Create new "eliminated" BoxLock node and use it in monitor debug info |
|
1910 |
// instead of oldbox for the same object. |
|
11458
5ba160829cef
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
11446
diff
changeset
|
1911 |
BoxLockNode* newbox = oldbox->clone()->as_BoxLock(); |
11445 | 1912 |
|
1913 |
// Note: BoxLock node is marked eliminated only here and it is used |
|
1914 |
// to indicate that all associated lock and unlock nodes are marked |
|
1915 |
// for elimination. |
|
1916 |
newbox->set_eliminated(); |
|
1917 |
transform_later(newbox); |
|
1918 |
||
1919 |
// Replace old box node with new box for all users of the same object. |
|
1920 |
for (uint i = 0; i < oldbox->outcnt();) { |
|
1921 |
bool next_edge = true; |
|
1922 |
||
1923 |
Node* u = oldbox->raw_out(i); |
|
1924 |
if (u->is_AbstractLock()) { |
|
1925 |
AbstractLockNode* alock = u->as_AbstractLock(); |
|
11446 | 1926 |
if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) { |
11445 | 1927 |
// Replace Box and mark eliminated all related locks and unlocks. |
1928 |
alock->set_non_esc_obj(); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1929 |
_igvn.rehash_node_delayed(alock); |
11445 | 1930 |
alock->set_box_node(newbox); |
1931 |
next_edge = false; |
|
1932 |
} |
|
1933 |
} |
|
11446 | 1934 |
if (u->is_FastLock() && u->as_FastLock()->obj_node()->eqv_uncast(obj)) { |
11445 | 1935 |
FastLockNode* flock = u->as_FastLock(); |
1936 |
assert(flock->box_node() == oldbox, "sanity"); |
|
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1937 |
_igvn.rehash_node_delayed(flock); |
11445 | 1938 |
flock->set_box_node(newbox); |
1939 |
next_edge = false; |
|
1940 |
} |
|
1941 |
||
1942 |
// Replace old box in monitor debug info. |
|
1943 |
if (u->is_SafePoint() && u->as_SafePoint()->jvms()) { |
|
1944 |
SafePointNode* sfn = u->as_SafePoint(); |
|
1945 |
JVMState* youngest_jvms = sfn->jvms(); |
|
1946 |
int max_depth = youngest_jvms->depth(); |
|
1947 |
for (int depth = 1; depth <= max_depth; depth++) { |
|
1948 |
JVMState* jvms = youngest_jvms->of_depth(depth); |
|
1949 |
int num_mon = jvms->nof_monitors(); |
|
1950 |
// Loop over monitors |
|
1951 |
for (int idx = 0; idx < num_mon; idx++) { |
|
1952 |
Node* obj_node = sfn->monitor_obj(jvms, idx); |
|
1953 |
Node* box_node = sfn->monitor_box(jvms, idx); |
|
11446 | 1954 |
if (box_node == oldbox && obj_node->eqv_uncast(obj)) { |
11445 | 1955 |
int j = jvms->monitor_box_offset(idx); |
12958
009b6c9586d8
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
11724
diff
changeset
|
1956 |
_igvn.replace_input_of(u, j, newbox); |
11445 | 1957 |
next_edge = false; |
1958 |
} |
|
1959 |
} |
|
1960 |
} |
|
1961 |
} |
|
1962 |
if (next_edge) i++; |
|
1963 |
} |
|
1964 |
} |
|
1965 |
||
1966 |
//-----------------------mark_eliminated_locking_nodes----------------------- |
|
1967 |
void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { |
|
1968 |
if (EliminateNestedLocks) { |
|
1969 |
if (alock->is_nested()) { |
|
1970 |
assert(alock->box_node()->as_BoxLock()->is_eliminated(), "sanity"); |
|
1971 |
return; |
|
1972 |
} else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened |
|
1973 |
// Only Lock node has JVMState needed here. |
|
1974 |
if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) { |
|
1975 |
// Mark eliminated related nested locks and unlocks. |
|
1976 |
Node* obj = alock->obj_node(); |
|
1977 |
BoxLockNode* box_node = alock->box_node()->as_BoxLock(); |
|
1978 |
assert(!box_node->is_eliminated(), "should not be marked yet"); |
|
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1979 |
// Note: BoxLock node is marked eliminated only here |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1980 |
// and it is used to indicate that all associated lock |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
1981 |
// and unlock nodes are marked for elimination. |
11445 | 1982 |
box_node->set_eliminated(); // Box's hash is always NO_HASH here |
1983 |
for (uint i = 0; i < box_node->outcnt(); i++) { |
|
1984 |
Node* u = box_node->raw_out(i); |
|
1985 |
if (u->is_AbstractLock()) { |
|
1986 |
alock = u->as_AbstractLock(); |
|
1987 |
if (alock->box_node() == box_node) { |
|
1988 |
// Verify that this Box is referenced only by related locks. |
|
11446 | 1989 |
assert(alock->obj_node()->eqv_uncast(obj), ""); |
11445 | 1990 |
// Mark all related locks and unlocks. |
1991 |
alock->set_nested(); |
|
1992 |
} |
|
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
1993 |
} |
11445 | 1994 |
} |
1995 |
} |
|
1996 |
return; |
|
1997 |
} |
|
1998 |
// Process locks for non escaping object |
|
1999 |
assert(alock->is_non_esc_obj(), ""); |
|
2000 |
} // EliminateNestedLocks |
|
2001 |
||
2002 |
if (alock->is_non_esc_obj()) { // Lock is used for non escaping object |
|
2003 |
// Look for all locks of this object and mark them and |
|
2004 |
// corresponding BoxLock nodes as eliminated. |
|
2005 |
Node* obj = alock->obj_node(); |
|
2006 |
for (uint j = 0; j < obj->outcnt(); j++) { |
|
2007 |
Node* o = obj->raw_out(j); |
|
11446 | 2008 |
if (o->is_AbstractLock() && |
2009 |
o->as_AbstractLock()->obj_node()->eqv_uncast(obj)) { |
|
11445 | 2010 |
alock = o->as_AbstractLock(); |
2011 |
Node* box = alock->box_node(); |
|
2012 |
// Replace old box node with new eliminated box for all users |
|
2013 |
// of the same object and mark related locks as eliminated. |
|
2014 |
mark_eliminated_box(box, obj); |
|
2015 |
} |
|
2016 |
} |
|
2017 |
} |
|
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2018 |
} |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2019 |
|
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2020 |
// we have determined that this lock/unlock can be eliminated, we simply |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2021 |
// eliminate the node without expanding it. |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2022 |
// |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2023 |
// Note: The membar's associated with the lock/unlock are currently not |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2024 |
// eliminated. This should be investigated as a future enhancement. |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2025 |
// |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2026 |
bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2027 |
|
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2028 |
if (!alock->is_eliminated()) { |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2029 |
return false; |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2030 |
} |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2031 |
#ifdef ASSERT |
11445 | 2032 |
if (!alock->is_coarsened()) { |
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2033 |
// Check that new "eliminated" BoxLock node is created. |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2034 |
BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2035 |
assert(oldbox->is_eliminated(), "should be done already"); |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2036 |
} |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2037 |
#endif |
4450
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2038 |
CompileLog* log = C->log(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2039 |
if (log != NULL) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2040 |
log->head("eliminate_lock lock='%d'", |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2041 |
alock->is_Lock()); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2042 |
JVMState* p = alock->jvms(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2043 |
while (p != NULL) { |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2044 |
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2045 |
p = p->caller(); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2046 |
} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2047 |
log->tail("eliminate_lock"); |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2048 |
} |
6d700b859b3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
3268
diff
changeset
|
2049 |
|
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2050 |
#ifndef PRODUCT |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2051 |
if (PrintEliminateLocks) { |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2052 |
if (alock->is_Lock()) { |
11191 | 2053 |
tty->print_cr("++++ Eliminated: %d Lock", alock->_idx); |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2054 |
} else { |
11191 | 2055 |
tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx); |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2056 |
} |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2057 |
} |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2058 |
#endif |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2059 |
|
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2060 |
Node* mem = alock->in(TypeFunc::Memory); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2061 |
Node* ctrl = alock->in(TypeFunc::Control); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2062 |
|
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2063 |
extract_call_projections(alock); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2064 |
// There are 2 projections from the lock. The lock node will |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2065 |
// be deleted when its last use is subsumed below. |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2066 |
assert(alock->outcnt() == 2 && |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2067 |
_fallthroughproj != NULL && |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2068 |
_memproj_fallthrough != NULL, |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2069 |
"Unexpected projections from Lock/Unlock"); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2070 |
|
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2071 |
Node* fallthroughproj = _fallthroughproj; |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2072 |
Node* memproj_fallthrough = _memproj_fallthrough; |
1 | 2073 |
|
2074 |
// The memory projection from a lock/unlock is RawMem |
|
2075 |
// The input to a Lock is merged memory, so extract its RawMem input |
|
2076 |
// (unless the MergeMem has been optimized away.) |
|
2077 |
if (alock->is_Lock()) { |
|
10262
c5f62d314bee
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
10011
diff
changeset
|
2078 |
// Seach for MemBarAcquireLock node and delete it also. |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2079 |
MemBarNode* membar = fallthroughproj->unique_ctrl_out()->as_MemBar(); |
10262
c5f62d314bee
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
10011
diff
changeset
|
2080 |
assert(membar != NULL && membar->Opcode() == Op_MemBarAcquireLock, ""); |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2081 |
Node* ctrlproj = membar->proj_out(TypeFunc::Control); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2082 |
Node* memproj = membar->proj_out(TypeFunc::Memory); |
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2083 |
_igvn.replace_node(ctrlproj, fallthroughproj); |
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2084 |
_igvn.replace_node(memproj, memproj_fallthrough); |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2085 |
|
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2086 |
// Delete FastLock node also if this Lock node is unique user |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2087 |
// (a loop peeling may clone a Lock node). |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2088 |
Node* flock = alock->as_Lock()->fastlock_node(); |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2089 |
if (flock->outcnt() == 1) { |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2090 |
assert(flock->unique_out() == alock, "sanity"); |
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2091 |
_igvn.replace_node(flock, top()); |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2092 |
} |
1 | 2093 |
} |
2094 |
||
10262
c5f62d314bee
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
10011
diff
changeset
|
2095 |
// Seach for MemBarReleaseLock node and delete it also. |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2096 |
if (alock->is_Unlock() && ctrl != NULL && ctrl->is_Proj() && |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2097 |
ctrl->in(0)->is_MemBar()) { |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2098 |
MemBarNode* membar = ctrl->in(0)->as_MemBar(); |
10262
c5f62d314bee
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
10011
diff
changeset
|
2099 |
assert(membar->Opcode() == Op_MemBarReleaseLock && |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2100 |
mem->is_Proj() && membar == mem->in(0), ""); |
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2101 |
_igvn.replace_node(fallthroughproj, ctrl); |
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2102 |
_igvn.replace_node(memproj_fallthrough, mem); |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2103 |
fallthroughproj = ctrl; |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2104 |
memproj_fallthrough = mem; |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2105 |
ctrl = membar->in(TypeFunc::Control); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2106 |
mem = membar->in(TypeFunc::Memory); |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2107 |
} |
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2108 |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2109 |
_igvn.replace_node(fallthroughproj, ctrl); |
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2110 |
_igvn.replace_node(memproj_fallthrough, mem); |
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2111 |
return true; |
1 | 2112 |
} |
2113 |
||
2114 |
||
2115 |
//------------------------------expand_lock_node---------------------- |
|
2116 |
void PhaseMacroExpand::expand_lock_node(LockNode *lock) { |
|
2117 |
||
2118 |
Node* ctrl = lock->in(TypeFunc::Control); |
|
2119 |
Node* mem = lock->in(TypeFunc::Memory); |
|
2120 |
Node* obj = lock->obj_node(); |
|
2121 |
Node* box = lock->box_node(); |
|
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2122 |
Node* flock = lock->fastlock_node(); |
1 | 2123 |
|
11458
5ba160829cef
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
11446
diff
changeset
|
2124 |
assert(!box->as_BoxLock()->is_eliminated(), "sanity"); |
11445 | 2125 |
|
1 | 2126 |
// Make the merge point |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2127 |
Node *region; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2128 |
Node *mem_phi; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2129 |
Node *slow_path; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2130 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2131 |
if (UseOptoBiasInlining) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2132 |
/* |
2131 | 2133 |
* See the full description in MacroAssembler::biased_locking_enter(). |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2134 |
* |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2135 |
* if( (mark_word & biased_lock_mask) == biased_lock_pattern ) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2136 |
* // The object is biased. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2137 |
* proto_node = klass->prototype_header; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2138 |
* o_node = thread | proto_node; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2139 |
* x_node = o_node ^ mark_word; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2140 |
* if( (x_node & ~age_mask) == 0 ) { // Biased to the current thread ? |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2141 |
* // Done. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2142 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2143 |
* if( (x_node & biased_lock_mask) != 0 ) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2144 |
* // The klass's prototype header is no longer biased. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2145 |
* cas(&mark_word, mark_word, proto_node) |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2146 |
* goto cas_lock; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2147 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2148 |
* // The klass's prototype header is still biased. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2149 |
* if( (x_node & epoch_mask) != 0 ) { // Expired epoch? |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2150 |
* old = mark_word; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2151 |
* new = o_node; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2152 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2153 |
* // Different thread or anonymous biased. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2154 |
* old = mark_word & (epoch_mask | age_mask | biased_lock_mask); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2155 |
* new = thread | old; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2156 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2157 |
* // Try to rebias. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2158 |
* if( cas(&mark_word, old, new) == 0 ) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2159 |
* // Done. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2160 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2161 |
* goto slow_path; // Failed. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2162 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2163 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2164 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2165 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2166 |
* // The object is not biased. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2167 |
* cas_lock: |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2168 |
* if( FastLock(obj) == 0 ) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2169 |
* // Done. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2170 |
* } else { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2171 |
* slow_path: |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2172 |
* OptoRuntime::complete_monitor_locking_Java(obj); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2173 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2174 |
* } |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2175 |
*/ |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2176 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2177 |
region = new RegionNode(5); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2178 |
// create a Phi for the memory state |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2179 |
mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2180 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2181 |
Node* fast_lock_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2182 |
Node* fast_lock_mem_phi = new PhiNode( fast_lock_region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2183 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2184 |
// First, check mark word for the biased lock pattern. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2185 |
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type()); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2186 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2187 |
// Get fast path - mark word has the biased lock pattern. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2188 |
ctrl = opt_bits_test(ctrl, fast_lock_region, 1, mark_node, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2189 |
markOopDesc::biased_lock_mask_in_place, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2190 |
markOopDesc::biased_lock_pattern, true); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2191 |
// fast_lock_region->in(1) is set to slow path. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2192 |
fast_lock_mem_phi->init_req(1, mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2193 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2194 |
// Now check that the lock is biased to the current thread and has |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2195 |
// the same epoch and bias as Klass::_prototype_header. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2196 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2197 |
// Special-case a fresh allocation to avoid building nodes: |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2198 |
Node* klass_node = AllocateNode::Ideal_klass(obj, &_igvn); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2199 |
if (klass_node == NULL) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2200 |
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); |
27637
cf68c0af6882
8057622: java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest: SEGV inside compiled code (sparc)
zmajo
parents:
26180
diff
changeset
|
2201 |
klass_node = transform_later(LoadKlassNode::make(_igvn, NULL, mem, k_adr, _igvn.type(k_adr)->is_ptr())); |
1677
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2202 |
#ifdef _LP64 |
19979
ebe1dbb6e1aa
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
19708
diff
changeset
|
2203 |
if (UseCompressedClassPointers && klass_node->is_DecodeNKlass()) { |
1677
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2204 |
assert(klass_node->in(1)->Opcode() == Op_LoadNKlass, "sanity"); |
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2205 |
klass_node->in(1)->init_req(0, ctrl); |
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2206 |
} else |
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2207 |
#endif |
f632e4c20c3e
6782820: Server VM fails with "unhandled implicit exception in compiled code"
kvn
parents:
1613
diff
changeset
|
2208 |
klass_node->init_req(0, ctrl); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2209 |
} |
11430
718fc06da49a
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
11191
diff
changeset
|
2210 |
Node *proto_node = make_load(ctrl, mem, klass_node, in_bytes(Klass::prototype_header_offset()), TypeX_X, TypeX_X->basic_type()); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2211 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2212 |
Node* thread = transform_later(new ThreadLocalNode()); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2213 |
Node* cast_thread = transform_later(new CastP2XNode(ctrl, thread)); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2214 |
Node* o_node = transform_later(new OrXNode(cast_thread, proto_node)); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2215 |
Node* x_node = transform_later(new XorXNode(o_node, mark_node)); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2216 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2217 |
// Get slow path - mark word does NOT match the value. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2218 |
Node* not_biased_ctrl = opt_bits_test(ctrl, region, 3, x_node, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2219 |
(~markOopDesc::age_mask_in_place), 0); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2220 |
// region->in(3) is set to fast path - the object is biased to the current thread. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2221 |
mem_phi->init_req(3, mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2222 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2223 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2224 |
// Mark word does NOT match the value (thread | Klass::_prototype_header). |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2225 |
|
1 | 2226 |
|
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2227 |
// First, check biased pattern. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2228 |
// Get fast path - _prototype_header has the same biased lock pattern. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2229 |
ctrl = opt_bits_test(not_biased_ctrl, fast_lock_region, 2, x_node, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2230 |
markOopDesc::biased_lock_mask_in_place, 0, true); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2231 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2232 |
not_biased_ctrl = fast_lock_region->in(2); // Slow path |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2233 |
// fast_lock_region->in(2) - the prototype header is no longer biased |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2234 |
// and we have to revoke the bias on this object. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2235 |
// We are going to try to reset the mark of this object to the prototype |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2236 |
// value and fall through to the CAS-based locking scheme. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2237 |
Node* adr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2238 |
Node* cas = new StoreXConditionalNode(not_biased_ctrl, mem, adr, |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2239 |
proto_node, mark_node); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2240 |
transform_later(cas); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2241 |
Node* proj = transform_later(new SCMemProjNode(cas)); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2242 |
fast_lock_mem_phi->init_req(2, proj); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2243 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2244 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2245 |
// Second, check epoch bits. |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2246 |
Node* rebiased_region = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2247 |
Node* old_phi = new PhiNode( rebiased_region, TypeX_X); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2248 |
Node* new_phi = new PhiNode( rebiased_region, TypeX_X); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2249 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2250 |
// Get slow path - mark word does NOT match epoch bits. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2251 |
Node* epoch_ctrl = opt_bits_test(ctrl, rebiased_region, 1, x_node, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2252 |
markOopDesc::epoch_mask_in_place, 0); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2253 |
// The epoch of the current bias is not valid, attempt to rebias the object |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2254 |
// toward the current thread. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2255 |
rebiased_region->init_req(2, epoch_ctrl); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2256 |
old_phi->init_req(2, mark_node); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2257 |
new_phi->init_req(2, o_node); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2258 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2259 |
// rebiased_region->in(1) is set to fast path. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2260 |
// The epoch of the current bias is still valid but we know |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2261 |
// nothing about the owner; it might be set or it might be clear. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2262 |
Node* cmask = MakeConX(markOopDesc::biased_lock_mask_in_place | |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2263 |
markOopDesc::age_mask_in_place | |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2264 |
markOopDesc::epoch_mask_in_place); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2265 |
Node* old = transform_later(new AndXNode(mark_node, cmask)); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2266 |
cast_thread = transform_later(new CastP2XNode(ctrl, thread)); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2267 |
Node* new_mark = transform_later(new OrXNode(cast_thread, old)); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2268 |
old_phi->init_req(1, old); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2269 |
new_phi->init_req(1, new_mark); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2270 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2271 |
transform_later(rebiased_region); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2272 |
transform_later(old_phi); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2273 |
transform_later(new_phi); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2274 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2275 |
// Try to acquire the bias of the object using an atomic operation. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2276 |
// If this fails we will go in to the runtime to revoke the object's bias. |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2277 |
cas = new StoreXConditionalNode(rebiased_region, mem, adr, new_phi, old_phi); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2278 |
transform_later(cas); |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2279 |
proj = transform_later(new SCMemProjNode(cas)); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2280 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2281 |
// Get slow path - Failed to CAS. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2282 |
not_biased_ctrl = opt_bits_test(rebiased_region, region, 4, cas, 0, 0); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2283 |
mem_phi->init_req(4, proj); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2284 |
// region->in(4) is set to fast path - the object is rebiased to the current thread. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2285 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2286 |
// Failed to CAS. |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2287 |
slow_path = new RegionNode(3); |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2288 |
Node *slow_mem = new PhiNode( slow_path, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2289 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2290 |
slow_path->init_req(1, not_biased_ctrl); // Capture slow-control |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2291 |
slow_mem->init_req(1, proj); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2292 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2293 |
// Call CAS-based locking scheme (FastLock node). |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2294 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2295 |
transform_later(fast_lock_region); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2296 |
transform_later(fast_lock_mem_phi); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2297 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2298 |
// Get slow path - FastLock failed to lock the object. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2299 |
ctrl = opt_bits_test(fast_lock_region, region, 2, flock, 0, 0); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2300 |
mem_phi->init_req(2, fast_lock_mem_phi); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2301 |
// region->in(2) is set to fast path - the object is locked to the current thread. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2302 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2303 |
slow_path->init_req(2, ctrl); // Capture slow-control |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2304 |
slow_mem->init_req(2, fast_lock_mem_phi); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2305 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2306 |
transform_later(slow_path); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2307 |
transform_later(slow_mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2308 |
// Reset lock's memory edge. |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2309 |
lock->set_req(TypeFunc::Memory, slow_mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2310 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2311 |
} else { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2312 |
region = new RegionNode(3); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2313 |
// create a Phi for the memory state |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2314 |
mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2315 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2316 |
// Optimize test; set region slot 2 |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2317 |
slow_path = opt_bits_test(ctrl, region, 2, flock, 0, 0); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2318 |
mem_phi->init_req(2, mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2319 |
} |
1 | 2320 |
|
2321 |
// Make slow path call |
|
2322 |
CallNode *call = make_slow_call( (CallNode *) lock, OptoRuntime::complete_monitor_enter_Type(), OptoRuntime::complete_monitor_locking_Java(), NULL, slow_path, obj, box ); |
|
2323 |
||
2324 |
extract_call_projections(call); |
|
2325 |
||
2326 |
// Slow path can only throw asynchronous exceptions, which are always |
|
2327 |
// de-opted. So the compiler thinks the slow-call can never throw an |
|
2328 |
// exception. If it DOES throw an exception we would need the debug |
|
2329 |
// info removed first (since if it throws there is no monitor). |
|
2330 |
assert ( _ioproj_fallthrough == NULL && _ioproj_catchall == NULL && |
|
2331 |
_memproj_catchall == NULL && _catchallcatchproj == NULL, "Unexpected projection from Lock"); |
|
2332 |
||
2333 |
// Capture slow path |
|
2334 |
// disconnect fall-through projection from call and create a new one |
|
2335 |
// hook up users of fall-through projection to region |
|
2336 |
Node *slow_ctrl = _fallthroughproj->clone(); |
|
2337 |
transform_later(slow_ctrl); |
|
2338 |
_igvn.hash_delete(_fallthroughproj); |
|
14623
70c4c1be0a14
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
13969
diff
changeset
|
2339 |
_fallthroughproj->disconnect_inputs(NULL, C); |
1 | 2340 |
region->init_req(1, slow_ctrl); |
2341 |
// region inputs are now complete |
|
2342 |
transform_later(region); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2343 |
_igvn.replace_node(_fallthroughproj, region); |
1 | 2344 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2345 |
Node *memproj = transform_later(new ProjNode(call, TypeFunc::Memory)); |
1 | 2346 |
mem_phi->init_req(1, memproj ); |
2347 |
transform_later(mem_phi); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2348 |
_igvn.replace_node(_memproj_fallthrough, mem_phi); |
1 | 2349 |
} |
2350 |
||
2351 |
//------------------------------expand_unlock_node---------------------- |
|
2352 |
void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { |
|
2353 |
||
239
fb31825d5444
6672848: (Escape Analysis) improve lock elimination with EA
kvn
parents:
236
diff
changeset
|
2354 |
Node* ctrl = unlock->in(TypeFunc::Control); |
1 | 2355 |
Node* mem = unlock->in(TypeFunc::Memory); |
2356 |
Node* obj = unlock->obj_node(); |
|
2357 |
Node* box = unlock->box_node(); |
|
2358 |
||
11458
5ba160829cef
7128355: assert(!nocreate) failed: Cannot build a phi for a block already parsed
kvn
parents:
11446
diff
changeset
|
2359 |
assert(!box->as_BoxLock()->is_eliminated(), "sanity"); |
11445 | 2360 |
|
1 | 2361 |
// No need for a null check on unlock |
2362 |
||
2363 |
// Make the merge point |
|
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2364 |
Node *region; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2365 |
Node *mem_phi; |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2366 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2367 |
if (UseOptoBiasInlining) { |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2368 |
// Check for biased locking unlock case, which is a no-op. |
2131 | 2369 |
// See the full description in MacroAssembler::biased_locking_exit(). |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2370 |
region = new RegionNode(4); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2371 |
// create a Phi for the memory state |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2372 |
mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2373 |
mem_phi->init_req(3, mem); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2374 |
|
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2375 |
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type()); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2376 |
ctrl = opt_bits_test(ctrl, region, 3, mark_node, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2377 |
markOopDesc::biased_lock_mask_in_place, |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2378 |
markOopDesc::biased_lock_pattern); |
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2379 |
} else { |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2380 |
region = new RegionNode(3); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2381 |
// create a Phi for the memory state |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2382 |
mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); |
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2383 |
} |
1 | 2384 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2385 |
FastUnlockNode *funlock = new FastUnlockNode( ctrl, obj, box ); |
1 | 2386 |
funlock = transform_later( funlock )->as_FastUnlock(); |
2387 |
// Optimize test; set region slot 2 |
|
1500
bea9a90f3e8f
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
1394
diff
changeset
|
2388 |
Node *slow_path = opt_bits_test(ctrl, region, 2, funlock, 0, 0); |
1 | 2389 |
|
2390 |
CallNode *call = make_slow_call( (CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), "complete_monitor_unlocking_C", slow_path, obj, box ); |
|
2391 |
||
2392 |
extract_call_projections(call); |
|
2393 |
||
2394 |
assert ( _ioproj_fallthrough == NULL && _ioproj_catchall == NULL && |
|
2395 |
_memproj_catchall == NULL && _catchallcatchproj == NULL, "Unexpected projection from Lock"); |
|
2396 |
||
2397 |
// No exceptions for unlocking |
|
2398 |
// Capture slow path |
|
2399 |
// disconnect fall-through projection from call and create a new one |
|
2400 |
// hook up users of fall-through projection to region |
|
2401 |
Node *slow_ctrl = _fallthroughproj->clone(); |
|
2402 |
transform_later(slow_ctrl); |
|
2403 |
_igvn.hash_delete(_fallthroughproj); |
|
14623
70c4c1be0a14
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
13969
diff
changeset
|
2404 |
_fallthroughproj->disconnect_inputs(NULL, C); |
1 | 2405 |
region->init_req(1, slow_ctrl); |
2406 |
// region inputs are now complete |
|
2407 |
transform_later(region); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2408 |
_igvn.replace_node(_fallthroughproj, region); |
1 | 2409 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
2410 |
Node *memproj = transform_later(new ProjNode(call, TypeFunc::Memory) ); |
1 | 2411 |
mem_phi->init_req(1, memproj ); |
2412 |
mem_phi->init_req(2, mem); |
|
2413 |
transform_later(mem_phi); |
|
2532
da0b1680593b
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
2154
diff
changeset
|
2414 |
_igvn.replace_node(_memproj_fallthrough, mem_phi); |
1 | 2415 |
} |
2416 |
||
11191 | 2417 |
//---------------------------eliminate_macro_nodes---------------------- |
2418 |
// Eliminate scalar replaced allocations and associated locks. |
|
2419 |
void PhaseMacroExpand::eliminate_macro_nodes() { |
|
1 | 2420 |
if (C->macro_count() == 0) |
11191 | 2421 |
return; |
2422 |
||
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2423 |
// First, attempt to eliminate locks |
9977
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2424 |
int cnt = C->macro_count(); |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2425 |
for (int i=0; i < cnt; i++) { |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2426 |
Node *n = C->macro_node(i); |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2427 |
if (n->is_AbstractLock()) { // Lock and Unlock nodes |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2428 |
// Before elimination mark all associated (same box and obj) |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2429 |
// lock and unlock nodes. |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2430 |
mark_eliminated_locking_nodes(n->as_AbstractLock()); |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2431 |
} |
c23d1a8dcaa9
7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity
kvn
parents:
9446
diff
changeset
|
2432 |
} |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2433 |
bool progress = true; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2434 |
while (progress) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2435 |
progress = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2436 |
for (int i = C->macro_count(); i > 0; i--) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2437 |
Node * n = C->macro_node(i-1); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2438 |
bool success = false; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2439 |
debug_only(int old_macro_count = C->macro_count();); |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2440 |
if (n->is_AbstractLock()) { |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2441 |
success = eliminate_locking_node(n->as_AbstractLock()); |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2442 |
} |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2443 |
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2444 |
progress = progress || success; |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2445 |
} |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2446 |
} |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2447 |
// Next, attempt to eliminate allocations |
23491 | 2448 |
_has_locks = false; |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2449 |
progress = true; |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2450 |
while (progress) { |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2451 |
progress = false; |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2452 |
for (int i = C->macro_count(); i > 0; i--) { |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2453 |
Node * n = C->macro_node(i-1); |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2454 |
bool success = false; |
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2455 |
debug_only(int old_macro_count = C->macro_count();); |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2456 |
switch (n->class_id()) { |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2457 |
case Node::Class_Allocate: |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2458 |
case Node::Class_AllocateArray: |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2459 |
success = eliminate_allocate_node(n->as_Allocate()); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2460 |
break; |
17383 | 2461 |
case Node::Class_CallStaticJava: |
2462 |
success = eliminate_boxing_node(n->as_CallStaticJava()); |
|
2463 |
break; |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2464 |
case Node::Class_Lock: |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2465 |
case Node::Class_Unlock: |
1613
be097ec639a2
6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
kvn
parents:
1555
diff
changeset
|
2466 |
assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); |
23491 | 2467 |
_has_locks = true; |
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2468 |
break; |
26166 | 2469 |
case Node::Class_ArrayCopy: |
2470 |
break; |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2471 |
default: |
11191 | 2472 |
assert(n->Opcode() == Op_LoopLimit || |
2473 |
n->Opcode() == Op_Opaque1 || |
|
23491 | 2474 |
n->Opcode() == Op_Opaque2 || |
2475 |
n->Opcode() == Op_Opaque3, "unknown node type in macro list"); |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2476 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2477 |
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2478 |
progress = progress || success; |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2479 |
} |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2480 |
} |
11191 | 2481 |
} |
2482 |
||
2483 |
//------------------------------expand_macro_nodes---------------------- |
|
2484 |
// Returns true if a failure occurred. |
|
2485 |
bool PhaseMacroExpand::expand_macro_nodes() { |
|
2486 |
// Last attempt to eliminate macro nodes. |
|
2487 |
eliminate_macro_nodes(); |
|
2488 |
||
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2489 |
// Make sure expansion will not cause node limit to be exceeded. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2490 |
// Worst case is a macro node gets expanded into about 50 nodes. |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2491 |
// Allow 50% more for optimization. |
1 | 2492 |
if (C->check_node_count(C->macro_count() * 75, "out of nodes before macro expansion" ) ) |
2493 |
return true; |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2494 |
|
11191 | 2495 |
// Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations. |
2496 |
bool progress = true; |
|
2497 |
while (progress) { |
|
2498 |
progress = false; |
|
2499 |
for (int i = C->macro_count(); i > 0; i--) { |
|
2500 |
Node * n = C->macro_node(i-1); |
|
2501 |
bool success = false; |
|
2502 |
debug_only(int old_macro_count = C->macro_count();); |
|
2503 |
if (n->Opcode() == Op_LoopLimit) { |
|
2504 |
// Remove it from macro list and put on IGVN worklist to optimize. |
|
2505 |
C->remove_macro_node(n); |
|
2506 |
_igvn._worklist.push(n); |
|
2507 |
success = true; |
|
17383 | 2508 |
} else if (n->Opcode() == Op_CallStaticJava) { |
2509 |
// Remove it from macro list and put on IGVN worklist to optimize. |
|
2510 |
C->remove_macro_node(n); |
|
2511 |
_igvn._worklist.push(n); |
|
2512 |
success = true; |
|
11191 | 2513 |
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { |
2514 |
_igvn.replace_node(n, n->in(1)); |
|
2515 |
success = true; |
|
23491 | 2516 |
#if INCLUDE_RTM_OPT |
2517 |
} else if ((n->Opcode() == Op_Opaque3) && ((Opaque3Node*)n)->rtm_opt()) { |
|
2518 |
assert(C->profile_rtm(), "should be used only in rtm deoptimization code"); |
|
2519 |
assert((n->outcnt() == 1) && n->unique_out()->is_Cmp(), ""); |
|
2520 |
Node* cmp = n->unique_out(); |
|
2521 |
#ifdef ASSERT |
|
2522 |
// Validate graph. |
|
2523 |
assert((cmp->outcnt() == 1) && cmp->unique_out()->is_Bool(), ""); |
|
2524 |
BoolNode* bol = cmp->unique_out()->as_Bool(); |
|
2525 |
assert((bol->outcnt() == 1) && bol->unique_out()->is_If() && |
|
2526 |
(bol->_test._test == BoolTest::ne), ""); |
|
2527 |
IfNode* ifn = bol->unique_out()->as_If(); |
|
2528 |
assert((ifn->outcnt() == 2) && |
|
2529 |
ifn->proj_out(1)->is_uncommon_trap_proj(Deoptimization::Reason_rtm_state_change), ""); |
|
2530 |
#endif |
|
2531 |
Node* repl = n->in(1); |
|
2532 |
if (!_has_locks) { |
|
2533 |
// Remove RTM state check if there are no locks in the code. |
|
2534 |
// Replace input to compare the same value. |
|
2535 |
repl = (cmp->in(1) == n) ? cmp->in(2) : cmp->in(1); |
|
2536 |
} |
|
2537 |
_igvn.replace_node(n, repl); |
|
2538 |
success = true; |
|
2539 |
#endif |
|
11191 | 2540 |
} |
2541 |
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); |
|
2542 |
progress = progress || success; |
|
2543 |
} |
|
2544 |
} |
|
2545 |
||
26166 | 2546 |
// expand arraycopy "macro" nodes first |
2547 |
// For ReduceBulkZeroing, we must first process all arraycopy nodes |
|
2548 |
// before the allocate nodes are expanded. |
|
2549 |
int macro_idx = C->macro_count() - 1; |
|
2550 |
while (macro_idx >= 0) { |
|
2551 |
Node * n = C->macro_node(macro_idx); |
|
2552 |
assert(n->is_macro(), "only macro nodes expected here"); |
|
2553 |
if (_igvn.type(n) == Type::TOP || n->in(0)->is_top() ) { |
|
2554 |
// node is unreachable, so don't try to expand it |
|
2555 |
C->remove_macro_node(n); |
|
2556 |
} else if (n->is_ArrayCopy()){ |
|
2557 |
int macro_count = C->macro_count(); |
|
2558 |
expand_arraycopy_node(n->as_ArrayCopy()); |
|
2559 |
assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); |
|
2560 |
} |
|
2561 |
if (C->failing()) return true; |
|
2562 |
macro_idx --; |
|
2563 |
} |
|
2564 |
||
1 | 2565 |
// expand "macro" nodes |
2566 |
// nodes are removed from the macro list as they are processed |
|
2567 |
while (C->macro_count() > 0) { |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2568 |
int macro_count = C->macro_count(); |
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2569 |
Node * n = C->macro_node(macro_count-1); |
1 | 2570 |
assert(n->is_macro(), "only macro nodes expected here"); |
2571 |
if (_igvn.type(n) == Type::TOP || n->in(0)->is_top() ) { |
|
2572 |
// node is unreachable, so don't try to expand it |
|
2573 |
C->remove_macro_node(n); |
|
2574 |
continue; |
|
2575 |
} |
|
2576 |
switch (n->class_id()) { |
|
2577 |
case Node::Class_Allocate: |
|
2578 |
expand_allocate(n->as_Allocate()); |
|
2579 |
break; |
|
2580 |
case Node::Class_AllocateArray: |
|
2581 |
expand_allocate_array(n->as_AllocateArray()); |
|
2582 |
break; |
|
2583 |
case Node::Class_Lock: |
|
2584 |
expand_lock_node(n->as_Lock()); |
|
2585 |
break; |
|
2586 |
case Node::Class_Unlock: |
|
2587 |
expand_unlock_node(n->as_Unlock()); |
|
2588 |
break; |
|
2589 |
default: |
|
2590 |
assert(false, "unknown node type in macro list"); |
|
2591 |
} |
|
246
b029af7e69d3
6259129: (Escape Analysis) scalar replacement for not escaping objects
kvn
parents:
239
diff
changeset
|
2592 |
assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); |
1 | 2593 |
if (C->failing()) return true; |
2594 |
} |
|
360
21d113ecbf6a
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
246
diff
changeset
|
2595 |
|
21d113ecbf6a
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
246
diff
changeset
|
2596 |
_igvn.set_delay_transform(false); |
1 | 2597 |
_igvn.optimize(); |
11191 | 2598 |
if (C->failing()) return true; |
1 | 2599 |
return false; |
2600 |
} |