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