Mercurial > hg > graal-compiler
annotate src/share/vm/opto/memnode.cpp @ 10185:d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime.
Reviewed-by: twisti, johnc
Contributed-by: Martin Doerr <martin.doerr@sap.com>
author | johnc |
---|---|
date | Wed, 24 Apr 2013 14:48:43 -0700 |
parents | ff55877839bc |
children | 6f3fd5150b67 |
rev | line source |
---|---|
0 | 1 /* |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
6139
diff
changeset
|
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1100
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1100
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1100
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "compiler/compileLog.hpp" | |
28 #include "memory/allocation.inline.hpp" | |
29 #include "oops/objArrayKlass.hpp" | |
30 #include "opto/addnode.hpp" | |
31 #include "opto/cfgnode.hpp" | |
32 #include "opto/compile.hpp" | |
33 #include "opto/connode.hpp" | |
34 #include "opto/loopnode.hpp" | |
35 #include "opto/machnode.hpp" | |
36 #include "opto/matcher.hpp" | |
37 #include "opto/memnode.hpp" | |
38 #include "opto/mulnode.hpp" | |
39 #include "opto/phaseX.hpp" | |
40 #include "opto/regmask.hpp" | |
41 | |
0 | 42 // Portions of code courtesy of Clifford Click |
43 | |
44 // Optimization - Graph Style | |
45 | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
46 static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const TypePtr *tp, const TypePtr *adr_check, outputStream *st); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
47 |
0 | 48 //============================================================================= |
49 uint MemNode::size_of() const { return sizeof(*this); } | |
50 | |
51 const TypePtr *MemNode::adr_type() const { | |
52 Node* adr = in(Address); | |
53 const TypePtr* cross_check = NULL; | |
54 DEBUG_ONLY(cross_check = _adr_type); | |
55 return calculate_adr_type(adr->bottom_type(), cross_check); | |
56 } | |
57 | |
58 #ifndef PRODUCT | |
59 void MemNode::dump_spec(outputStream *st) const { | |
60 if (in(Address) == NULL) return; // node is dead | |
61 #ifndef ASSERT | |
62 // fake the missing field | |
63 const TypePtr* _adr_type = NULL; | |
64 if (in(Address) != NULL) | |
65 _adr_type = in(Address)->bottom_type()->isa_ptr(); | |
66 #endif | |
67 dump_adr_type(this, _adr_type, st); | |
68 | |
69 Compile* C = Compile::current(); | |
70 if( C->alias_type(_adr_type)->is_volatile() ) | |
71 st->print(" Volatile!"); | |
72 } | |
73 | |
74 void MemNode::dump_adr_type(const Node* mem, const TypePtr* adr_type, outputStream *st) { | |
75 st->print(" @"); | |
76 if (adr_type == NULL) { | |
77 st->print("NULL"); | |
78 } else { | |
79 adr_type->dump_on(st); | |
80 Compile* C = Compile::current(); | |
81 Compile::AliasType* atp = NULL; | |
82 if (C->have_alias_type(adr_type)) atp = C->alias_type(adr_type); | |
83 if (atp == NULL) | |
84 st->print(", idx=?\?;"); | |
85 else if (atp->index() == Compile::AliasIdxBot) | |
86 st->print(", idx=Bot;"); | |
87 else if (atp->index() == Compile::AliasIdxTop) | |
88 st->print(", idx=Top;"); | |
89 else if (atp->index() == Compile::AliasIdxRaw) | |
90 st->print(", idx=Raw;"); | |
91 else { | |
92 ciField* field = atp->field(); | |
93 if (field) { | |
94 st->print(", name="); | |
95 field->print_name_on(st); | |
96 } | |
97 st->print(", idx=%d;", atp->index()); | |
98 } | |
99 } | |
100 } | |
101 | |
102 extern void print_alias_types(); | |
103 | |
104 #endif | |
105 | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
106 Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
107 const TypeOopPtr *tinst = t_adr->isa_oopptr(); |
223 | 108 if (tinst == NULL || !tinst->is_known_instance_field()) |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
109 return mchain; // don't try to optimize non-instance types |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
110 uint instance_id = tinst->instance_id(); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
111 Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory); |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
112 Node *prev = NULL; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
113 Node *result = mchain; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
114 while (prev != result) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
115 prev = result; |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
116 if (result == start_mem) |
605 | 117 break; // hit one of our sentinels |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
118 // skip over a call which does not affect this memory slice |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
119 if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
120 Node *proj_in = result->in(0); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
121 if (proj_in->is_Allocate() && proj_in->_idx == instance_id) { |
605 | 122 break; // hit one of our sentinels |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
123 } else if (proj_in->is_Call()) { |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
124 CallNode *call = proj_in->as_Call(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
125 if (!call->may_modify(t_adr, phase)) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
126 result = call->in(TypeFunc::Memory); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
127 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
128 } else if (proj_in->is_Initialize()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
129 AllocateNode* alloc = proj_in->as_Initialize()->allocation(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
130 // Stop if this is the initialization for the object instance which |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
131 // which contains this memory slice, otherwise skip over it. |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
132 if (alloc != NULL && alloc->_idx != instance_id) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
133 result = proj_in->in(TypeFunc::Memory); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
134 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
135 } else if (proj_in->is_MemBar()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
136 result = proj_in->in(TypeFunc::Memory); |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
137 } else { |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
247
diff
changeset
|
138 assert(false, "unexpected projection"); |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
139 } |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
140 } else if (result->is_ClearArray()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
141 if (!ClearArrayNode::step_through(&result, instance_id, phase)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
142 // Can not bypass initialization of the instance |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
143 // we are looking for. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
144 break; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
145 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
146 // Otherwise skip it (the call updated 'result' value). |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
147 } else if (result->is_MergeMem()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
148 result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
149 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
150 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
151 return result; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
152 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
153 |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
154 Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
155 const TypeOopPtr *t_oop = t_adr->isa_oopptr(); |
223 | 156 bool is_instance = (t_oop != NULL) && t_oop->is_known_instance_field(); |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
157 PhaseIterGVN *igvn = phase->is_IterGVN(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
158 Node *result = mchain; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
159 result = optimize_simple_memory_chain(result, t_adr, phase); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
160 if (is_instance && igvn != NULL && result->is_Phi()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
161 PhiNode *mphi = result->as_Phi(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
162 assert(mphi->bottom_type() == Type::MEMORY, "memory phi required"); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
163 const TypePtr *t = mphi->adr_type(); |
163 | 164 if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || |
223 | 165 t->isa_oopptr() && !t->is_oopptr()->is_known_instance() && |
247 | 166 t->is_oopptr()->cast_to_exactness(true) |
167 ->is_oopptr()->cast_to_ptr_type(t_oop->ptr()) | |
168 ->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop) { | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
169 // clone the Phi with our address type |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
170 result = mphi->split_out_instance(t_adr, igvn); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
171 } else { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
172 assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain"); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
173 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
174 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
175 return result; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
176 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
177 |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
178 static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const TypePtr *tp, const TypePtr *adr_check, outputStream *st) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
179 uint alias_idx = phase->C->get_alias_index(tp); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
180 Node *mem = mmem; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
181 #ifdef ASSERT |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
182 { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
183 // Check that current type is consistent with the alias index used during graph construction |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
184 assert(alias_idx >= Compile::AliasIdxRaw, "must not be a bad alias_idx"); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
185 bool consistent = adr_check == NULL || adr_check->empty() || |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
186 phase->C->must_alias(adr_check, alias_idx ); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
187 // Sometimes dead array references collapse to a[-1], a[-2], or a[-3] |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
188 if( !consistent && adr_check != NULL && !adr_check->empty() && |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
168
diff
changeset
|
189 tp->isa_aryptr() && tp->offset() == Type::OffsetBot && |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
190 adr_check->isa_aryptr() && adr_check->offset() != Type::OffsetBot && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
191 ( adr_check->offset() == arrayOopDesc::length_offset_in_bytes() || |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
192 adr_check->offset() == oopDesc::klass_offset_in_bytes() || |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
193 adr_check->offset() == oopDesc::mark_offset_in_bytes() ) ) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
194 // don't assert if it is dead code. |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
195 consistent = true; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
196 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
197 if( !consistent ) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
198 st->print("alias_idx==%d, adr_check==", alias_idx); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
199 if( adr_check == NULL ) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
200 st->print("NULL"); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
201 } else { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
202 adr_check->dump(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
203 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
204 st->cr(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
205 print_alias_types(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
206 assert(consistent, "adr_check must match alias idx"); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
207 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
208 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
209 #endif |
1815 | 210 // TypeOopPtr::NOTNULL+any is an OOP with unknown offset - generally |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
211 // means an array I have not precisely typed yet. Do not do any |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
212 // alias stuff with it any time soon. |
1815 | 213 const TypeOopPtr *toop = tp->isa_oopptr(); |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
214 if( tp->base() != Type::AnyPtr && |
1815 | 215 !(toop && |
216 toop->klass() != NULL && | |
217 toop->klass()->is_java_lang_Object() && | |
218 toop->offset() == Type::OffsetBot) ) { | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
219 // compress paths and change unreachable cycles to TOP |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
220 // If not, we can update the input infinitely along a MergeMem cycle |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
221 // Equivalent code in PhiNode::Ideal |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
222 Node* m = phase->transform(mmem); |
605 | 223 // If transformed to a MergeMem, get the desired slice |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
224 // Otherwise the returned node represents memory for every slice |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
225 mem = (m->is_MergeMem())? m->as_MergeMem()->memory_at(alias_idx) : m; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
226 // Update input if it is progress over what we have now |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
227 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
228 return mem; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
229 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
230 |
0 | 231 //--------------------------Ideal_common--------------------------------------- |
232 // Look for degenerate control and memory inputs. Bypass MergeMem inputs. | |
233 // Unhook non-raw memories from complete (macro-expanded) initializations. | |
234 Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { | |
235 // If our control input is a dead region, kill all below the region | |
236 Node *ctl = in(MemNode::Control); | |
237 if (ctl && remove_dead_region(phase, can_reshape)) | |
238 return this; | |
305 | 239 ctl = in(MemNode::Control); |
240 // Don't bother trying to transform a dead node | |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
241 if (ctl && ctl->is_top()) return NodeSentinel; |
0 | 242 |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
243 PhaseIterGVN *igvn = phase->is_IterGVN(); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
244 // Wait if control on the worklist. |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
245 if (ctl && can_reshape && igvn != NULL) { |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
246 Node* bol = NULL; |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
247 Node* cmp = NULL; |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
248 if (ctl->in(0)->is_If()) { |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
249 assert(ctl->is_IfTrue() || ctl->is_IfFalse(), "sanity"); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
250 bol = ctl->in(0)->in(1); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
251 if (bol->is_Bool()) |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
252 cmp = ctl->in(0)->in(1)->in(1); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
253 } |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
254 if (igvn->_worklist.member(ctl) || |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
255 (bol != NULL && igvn->_worklist.member(bol)) || |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
256 (cmp != NULL && igvn->_worklist.member(cmp)) ) { |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
257 // This control path may be dead. |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
258 // Delay this memory node transformation until the control is processed. |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
259 phase->is_IterGVN()->_worklist.push(this); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
260 return NodeSentinel; // caller will return NULL |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
261 } |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
262 } |
0 | 263 // Ignore if memory is dead, or self-loop |
264 Node *mem = in(MemNode::Memory); | |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
265 if (phase->type( mem ) == Type::TOP) return NodeSentinel; // caller will return NULL |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
266 assert(mem != this, "dead loop in MemNode::Ideal"); |
0 | 267 |
4124
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
268 if (can_reshape && igvn != NULL && igvn->_worklist.member(mem)) { |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
269 // This memory slice may be dead. |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
270 // Delay this mem node transformation until the memory is processed. |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
271 phase->is_IterGVN()->_worklist.push(this); |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
272 return NodeSentinel; // caller will return NULL |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
273 } |
f745b2be3737
7117282: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)
kvn
parents:
4115
diff
changeset
|
274 |
0 | 275 Node *address = in(MemNode::Address); |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
276 const Type *t_adr = phase->type(address); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
277 if (t_adr == Type::TOP) return NodeSentinel; // caller will return NULL |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
278 |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
279 if (can_reshape && igvn != NULL && |
1826
56601ef83436
6916062: assert(_inserts <= _insert_limit,"hash table overflow") in NodeHash::hash_insert
kvn
parents:
1815
diff
changeset
|
280 (igvn->_worklist.member(address) || |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
281 igvn->_worklist.size() > 0 && (t_adr != adr_type())) ) { |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
282 // The address's base and type may change when the address is processed. |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
283 // Delay this mem node transformation until the address is processed. |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
284 phase->is_IterGVN()->_worklist.push(this); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
285 return NodeSentinel; // caller will return NULL |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
286 } |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
366
diff
changeset
|
287 |
1062
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
288 // Do NOT remove or optimize the next lines: ensure a new alias index |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
289 // is allocated for an oop pointer type before Escape Analysis. |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
290 // Note: C++ will not remove it since the call has side effect. |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
291 if (t_adr->isa_oopptr()) { |
1062
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
292 int alias_idx = phase->C->get_alias_index(t_adr->is_ptr()); |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
293 } |
dcdcc8c16e20
6896352: CTW fails hotspot/src/share/vm/opto/escape.cpp:1155
kvn
parents:
986
diff
changeset
|
294 |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
295 #ifdef ASSERT |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
296 Node* base = NULL; |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
297 if (address->is_AddP()) |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
298 base = address->in(AddPNode::Base); |
8695
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
299 if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) && |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
300 !t_adr->isa_rawptr()) { |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
301 // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true. |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
302 Compile* C = phase->C; |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
303 tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
304 tty->print_cr("===== NULL+offs not RAW address ====="); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
305 if (C->is_dead_node(this->_idx)) tty->print_cr("'this' is dead"); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
306 if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead"); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
307 if (C->is_dead_node(mem->_idx)) tty->print_cr("'mem' is dead"); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
308 if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead"); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
309 if (C->is_dead_node(base->_idx)) tty->print_cr("'base' is dead"); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
310 tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
311 base->dump(1); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
312 tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
313 this->dump(2); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
314 tty->print("this->adr_type(): "); adr_type()->dump(); tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
315 tty->print("phase->type(address): "); t_adr->dump(); tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
316 tty->print("phase->type(base): "); phase->type(address)->dump(); tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
317 tty->cr(); |
ff55877839bc
8009472: Print additional information for 8004640 failure
kvn
parents:
8116
diff
changeset
|
318 } |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
319 assert(base == NULL || t_adr->isa_rawptr() || |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
320 !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?"); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
321 #endif |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
322 |
0 | 323 // Avoid independent memory operations |
324 Node* old_mem = mem; | |
325 | |
36 | 326 // The code which unhooks non-raw memories from complete (macro-expanded) |
327 // initializations was removed. After macro-expansion all stores catched | |
328 // by Initialize node became raw stores and there is no information | |
329 // which memory slices they modify. So it is unsafe to move any memory | |
330 // operation above these stores. Also in most cases hooked non-raw memories | |
331 // were already unhooked by using information from detect_ptr_independence() | |
332 // and find_previous_store(). | |
0 | 333 |
334 if (mem->is_MergeMem()) { | |
335 MergeMemNode* mmem = mem->as_MergeMem(); | |
336 const TypePtr *tp = t_adr->is_ptr(); | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
337 |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
338 mem = step_through_mergemem(phase, mmem, tp, adr_type(), tty); |
0 | 339 } |
340 | |
341 if (mem != old_mem) { | |
342 set_req(MemNode::Memory, mem); | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
343 if (can_reshape && old_mem->outcnt() == 0) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
344 igvn->_worklist.push(old_mem); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
345 } |
305 | 346 if (phase->type( mem ) == Type::TOP) return NodeSentinel; |
0 | 347 return this; |
348 } | |
349 | |
350 // let the subclass continue analyzing... | |
351 return NULL; | |
352 } | |
353 | |
354 // Helper function for proving some simple control dominations. | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
355 // Attempt to prove that all control inputs of 'dom' dominate 'sub'. |
0 | 356 // Already assumes that 'dom' is available at 'sub', and that 'sub' |
357 // is not a constant (dominated by the method's StartNode). | |
358 // Used by MemNode::find_previous_store to prove that the | |
359 // control input of a memory operation predates (dominates) | |
360 // an allocation it wants to look past. | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
361 bool MemNode::all_controls_dominate(Node* dom, Node* sub) { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
362 if (dom == NULL || dom->is_top() || sub == NULL || sub->is_top()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
363 return false; // Conservative answer for dead code |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
364 |
193
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
365 // Check 'dom'. Skip Proj and CatchProj nodes. |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
366 dom = dom->find_exact_control(dom); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
367 if (dom == NULL || dom->is_top()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
368 return false; // Conservative answer for dead code |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
369 |
193
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
370 if (dom == sub) { |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
371 // For the case when, for example, 'sub' is Initialize and the original |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
372 // 'dom' is Proj node of the 'sub'. |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
373 return false; |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
374 } |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
375 |
155
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
376 if (dom->is_Con() || dom->is_Start() || dom->is_Root() || dom == sub) |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
377 return true; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
378 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
379 // 'dom' dominates 'sub' if its control edge and control edges |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
380 // of all its inputs dominate or equal to sub's control edge. |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
381 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
382 // Currently 'sub' is either Allocate, Initialize or Start nodes. |
163 | 383 // Or Region for the check in LoadNode::Ideal(); |
384 // 'sub' should have sub->in(0) != NULL. | |
385 assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start() || | |
386 sub->is_Region(), "expecting only these nodes"); | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
387 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
388 // Get control edge of 'sub'. |
193
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
389 Node* orig_sub = sub; |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
390 sub = sub->find_exact_control(sub->in(0)); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
391 if (sub == NULL || sub->is_top()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
392 return false; // Conservative answer for dead code |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
393 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
394 assert(sub->is_CFG(), "expecting control"); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
395 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
396 if (sub == dom) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
397 return true; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
398 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
399 if (sub->is_Start() || sub->is_Root()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
400 return false; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
401 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
402 { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
403 // Check all control edges of 'dom'. |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
404 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
405 ResourceMark rm; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
406 Arena* arena = Thread::current()->resource_area(); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
407 Node_List nlist(arena); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
408 Unique_Node_List dom_list(arena); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
409 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
410 dom_list.push(dom); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
411 bool only_dominating_controls = false; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
412 |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
413 for (uint next = 0; next < dom_list.size(); next++) { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
414 Node* n = dom_list.at(next); |
193
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
415 if (n == orig_sub) |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
416 return false; // One of dom's inputs dominated by sub. |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
417 if (!n->is_CFG() && n->pinned()) { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
418 // Check only own control edge for pinned non-control nodes. |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
419 n = n->find_exact_control(n->in(0)); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
420 if (n == NULL || n->is_top()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
421 return false; // Conservative answer for dead code |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
422 assert(n->is_CFG(), "expecting control"); |
193
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
423 dom_list.push(n); |
44a553b2809d
6714406: Node::dominates() does not always check for TOP
kvn
parents:
169
diff
changeset
|
424 } else if (n->is_Con() || n->is_Start() || n->is_Root()) { |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
425 only_dominating_controls = true; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
426 } else if (n->is_CFG()) { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
427 if (n->dominates(sub, nlist)) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
428 only_dominating_controls = true; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
429 else |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
430 return false; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
431 } else { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
432 // First, own control edge. |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
433 Node* m = n->find_exact_control(n->in(0)); |
155
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
434 if (m != NULL) { |
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
435 if (m->is_top()) |
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
436 return false; // Conservative answer for dead code |
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
437 dom_list.push(m); |
723be81c1212
6701887: JDK7 server VM in endless loop in Node::dominates
kvn
parents:
128
diff
changeset
|
438 } |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
439 // Now, the rest of edges. |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
440 uint cnt = n->req(); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
441 for (uint i = 1; i < cnt; i++) { |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
442 m = n->find_exact_control(n->in(i)); |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
443 if (m == NULL || m->is_top()) |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
444 continue; |
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
445 dom_list.push(m); |
0 | 446 } |
447 } | |
448 } | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
449 return only_dominating_controls; |
0 | 450 } |
451 } | |
452 | |
453 //---------------------detect_ptr_independence--------------------------------- | |
454 // Used by MemNode::find_previous_store to prove that two base | |
455 // pointers are never equal. | |
456 // The pointers are accompanied by their associated allocations, | |
457 // if any, which have been previously discovered by the caller. | |
458 bool MemNode::detect_ptr_independence(Node* p1, AllocateNode* a1, | |
459 Node* p2, AllocateNode* a2, | |
460 PhaseTransform* phase) { | |
461 // Attempt to prove that these two pointers cannot be aliased. | |
462 // They may both manifestly be allocations, and they should differ. | |
463 // Or, if they are not both allocations, they can be distinct constants. | |
464 // Otherwise, one is an allocation and the other a pre-existing value. | |
465 if (a1 == NULL && a2 == NULL) { // neither an allocation | |
466 return (p1 != p2) && p1->is_Con() && p2->is_Con(); | |
467 } else if (a1 != NULL && a2 != NULL) { // both allocations | |
468 return (a1 != a2); | |
469 } else if (a1 != NULL) { // one allocation a1 | |
470 // (Note: p2->is_Con implies p2->in(0)->is_Root, which dominates.) | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
471 return all_controls_dominate(p2, a1); |
0 | 472 } else { //(a2 != NULL) // one allocation a2 |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
473 return all_controls_dominate(p1, a2); |
0 | 474 } |
475 return false; | |
476 } | |
477 | |
478 | |
479 // The logic for reordering loads and stores uses four steps: | |
480 // (a) Walk carefully past stores and initializations which we | |
481 // can prove are independent of this load. | |
482 // (b) Observe that the next memory state makes an exact match | |
483 // with self (load or store), and locate the relevant store. | |
484 // (c) Ensure that, if we were to wire self directly to the store, | |
485 // the optimizer would fold it up somehow. | |
486 // (d) Do the rewiring, and return, depending on some other part of | |
487 // the optimizer to fold up the load. | |
488 // This routine handles steps (a) and (b). Steps (c) and (d) are | |
489 // specific to loads and stores, so they are handled by the callers. | |
490 // (Currently, only LoadNode::Ideal has steps (c), (d). More later.) | |
491 // | |
492 Node* MemNode::find_previous_store(PhaseTransform* phase) { | |
493 Node* ctrl = in(MemNode::Control); | |
494 Node* adr = in(MemNode::Address); | |
495 intptr_t offset = 0; | |
496 Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); | |
497 AllocateNode* alloc = AllocateNode::Ideal_allocation(base, phase); | |
498 | |
499 if (offset == Type::OffsetBot) | |
500 return NULL; // cannot unalias unless there are precise offsets | |
501 | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
502 const TypeOopPtr *addr_t = adr->bottom_type()->isa_oopptr(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
503 |
0 | 504 intptr_t size_in_bytes = memory_size(); |
505 | |
506 Node* mem = in(MemNode::Memory); // start searching here... | |
507 | |
508 int cnt = 50; // Cycle limiter | |
509 for (;;) { // While we can dance past unrelated stores... | |
510 if (--cnt < 0) break; // Caught in cycle or a complicated dance? | |
511 | |
512 if (mem->is_Store()) { | |
513 Node* st_adr = mem->in(MemNode::Address); | |
514 intptr_t st_offset = 0; | |
515 Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_offset); | |
516 if (st_base == NULL) | |
517 break; // inscrutable pointer | |
518 if (st_offset != offset && st_offset != Type::OffsetBot) { | |
519 const int MAX_STORE = BytesPerLong; | |
520 if (st_offset >= offset + size_in_bytes || | |
521 st_offset <= offset - MAX_STORE || | |
522 st_offset <= offset - mem->as_Store()->memory_size()) { | |
523 // Success: The offsets are provably independent. | |
524 // (You may ask, why not just test st_offset != offset and be done? | |
525 // The answer is that stores of different sizes can co-exist | |
526 // in the same sequence of RawMem effects. We sometimes initialize | |
527 // a whole 'tile' of array elements with a single jint or jlong.) | |
528 mem = mem->in(MemNode::Memory); | |
529 continue; // (a) advance through independent store memory | |
530 } | |
531 } | |
532 if (st_base != base && | |
533 detect_ptr_independence(base, alloc, | |
534 st_base, | |
535 AllocateNode::Ideal_allocation(st_base, phase), | |
536 phase)) { | |
537 // Success: The bases are provably independent. | |
538 mem = mem->in(MemNode::Memory); | |
539 continue; // (a) advance through independent store memory | |
540 } | |
541 | |
542 // (b) At this point, if the bases or offsets do not agree, we lose, | |
543 // since we have not managed to prove 'this' and 'mem' independent. | |
544 if (st_base == base && st_offset == offset) { | |
545 return mem; // let caller handle steps (c), (d) | |
546 } | |
547 | |
548 } else if (mem->is_Proj() && mem->in(0)->is_Initialize()) { | |
549 InitializeNode* st_init = mem->in(0)->as_Initialize(); | |
550 AllocateNode* st_alloc = st_init->allocation(); | |
551 if (st_alloc == NULL) | |
552 break; // something degenerated | |
553 bool known_identical = false; | |
554 bool known_independent = false; | |
555 if (alloc == st_alloc) | |
556 known_identical = true; | |
557 else if (alloc != NULL) | |
558 known_independent = true; | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
559 else if (all_controls_dominate(this, st_alloc)) |
0 | 560 known_independent = true; |
561 | |
562 if (known_independent) { | |
563 // The bases are provably independent: Either they are | |
564 // manifestly distinct allocations, or else the control | |
565 // of this load dominates the store's allocation. | |
566 int alias_idx = phase->C->get_alias_index(adr_type()); | |
567 if (alias_idx == Compile::AliasIdxRaw) { | |
568 mem = st_alloc->in(TypeFunc::Memory); | |
569 } else { | |
570 mem = st_init->memory(alias_idx); | |
571 } | |
572 continue; // (a) advance through independent store memory | |
573 } | |
574 | |
575 // (b) at this point, if we are not looking at a store initializing | |
576 // the same allocation we are loading from, we lose. | |
577 if (known_identical) { | |
578 // From caller, can_see_stored_value will consult find_captured_store. | |
579 return mem; // let caller handle steps (c), (d) | |
580 } | |
581 | |
223 | 582 } else if (addr_t != NULL && addr_t->is_known_instance_field()) { |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
583 // Can't use optimize_simple_memory_chain() since it needs PhaseGVN. |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
584 if (mem->is_Proj() && mem->in(0)->is_Call()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
585 CallNode *call = mem->in(0)->as_Call(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
586 if (!call->may_modify(addr_t, phase)) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
587 mem = call->in(TypeFunc::Memory); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
588 continue; // (a) advance through independent call memory |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
589 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
590 } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
591 mem = mem->in(0)->in(TypeFunc::Memory); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
592 continue; // (a) advance through independent MemBar memory |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
593 } else if (mem->is_ClearArray()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
594 if (ClearArrayNode::step_through(&mem, (uint)addr_t->instance_id(), phase)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
595 // (the call updated 'mem' value) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
596 continue; // (a) advance through independent allocation memory |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
597 } else { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
598 // Can not bypass initialization of the instance |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
599 // we are looking for. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
600 return mem; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
601 } |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
602 } else if (mem->is_MergeMem()) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
603 int alias_idx = phase->C->get_alias_index(adr_type()); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
604 mem = mem->as_MergeMem()->memory_at(alias_idx); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
605 continue; // (a) advance through independent MergeMem memory |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
606 } |
0 | 607 } |
608 | |
609 // Unless there is an explicit 'continue', we must bail out here, | |
610 // because 'mem' is an inscrutable memory state (e.g., a call). | |
611 break; | |
612 } | |
613 | |
614 return NULL; // bail out | |
615 } | |
616 | |
617 //----------------------calculate_adr_type------------------------------------- | |
618 // Helper function. Notices when the given type of address hits top or bottom. | |
619 // Also, asserts a cross-check of the type against the expected address type. | |
620 const TypePtr* MemNode::calculate_adr_type(const Type* t, const TypePtr* cross_check) { | |
621 if (t == Type::TOP) return NULL; // does not touch memory any more? | |
622 #ifdef PRODUCT | |
623 cross_check = NULL; | |
624 #else | |
625 if (!VerifyAliases || is_error_reported() || Node::in_dump()) cross_check = NULL; | |
626 #endif | |
627 const TypePtr* tp = t->isa_ptr(); | |
628 if (tp == NULL) { | |
629 assert(cross_check == NULL || cross_check == TypePtr::BOTTOM, "expected memory type must be wide"); | |
630 return TypePtr::BOTTOM; // touches lots of memory | |
631 } else { | |
632 #ifdef ASSERT | |
633 // %%%% [phh] We don't check the alias index if cross_check is | |
634 // TypeRawPtr::BOTTOM. Needs to be investigated. | |
635 if (cross_check != NULL && | |
636 cross_check != TypePtr::BOTTOM && | |
637 cross_check != TypeRawPtr::BOTTOM) { | |
638 // Recheck the alias index, to see if it has changed (due to a bug). | |
639 Compile* C = Compile::current(); | |
640 assert(C->get_alias_index(cross_check) == C->get_alias_index(tp), | |
641 "must stay in the original alias category"); | |
642 // The type of the address must be contained in the adr_type, | |
643 // disregarding "null"-ness. | |
644 // (We make an exception for TypeRawPtr::BOTTOM, which is a bit bucket.) | |
645 const TypePtr* tp_notnull = tp->join(TypePtr::NOTNULL)->is_ptr(); | |
646 assert(cross_check->meet(tp_notnull) == cross_check, | |
647 "real address must not escape from expected memory type"); | |
648 } | |
649 #endif | |
650 return tp; | |
651 } | |
652 } | |
653 | |
654 //------------------------adr_phi_is_loop_invariant---------------------------- | |
655 // A helper function for Ideal_DU_postCCP to check if a Phi in a counted | |
656 // loop is loop invariant. Make a quick traversal of Phi and associated | |
657 // CastPP nodes, looking to see if they are a closed group within the loop. | |
658 bool MemNode::adr_phi_is_loop_invariant(Node* adr_phi, Node* cast) { | |
659 // The idea is that the phi-nest must boil down to only CastPP nodes | |
660 // with the same data. This implies that any path into the loop already | |
661 // includes such a CastPP, and so the original cast, whatever its input, | |
662 // must be covered by an equivalent cast, with an earlier control input. | |
663 ResourceMark rm; | |
664 | |
665 // The loop entry input of the phi should be the unique dominating | |
666 // node for every Phi/CastPP in the loop. | |
667 Unique_Node_List closure; | |
668 closure.push(adr_phi->in(LoopNode::EntryControl)); | |
669 | |
670 // Add the phi node and the cast to the worklist. | |
671 Unique_Node_List worklist; | |
672 worklist.push(adr_phi); | |
673 if( cast != NULL ){ | |
674 if( !cast->is_ConstraintCast() ) return false; | |
675 worklist.push(cast); | |
676 } | |
677 | |
678 // Begin recursive walk of phi nodes. | |
679 while( worklist.size() ){ | |
680 // Take a node off the worklist | |
681 Node *n = worklist.pop(); | |
682 if( !closure.member(n) ){ | |
683 // Add it to the closure. | |
684 closure.push(n); | |
685 // Make a sanity check to ensure we don't waste too much time here. | |
686 if( closure.size() > 20) return false; | |
687 // This node is OK if: | |
688 // - it is a cast of an identical value | |
689 // - or it is a phi node (then we add its inputs to the worklist) | |
690 // Otherwise, the node is not OK, and we presume the cast is not invariant | |
691 if( n->is_ConstraintCast() ){ | |
692 worklist.push(n->in(1)); | |
693 } else if( n->is_Phi() ) { | |
694 for( uint i = 1; i < n->req(); i++ ) { | |
695 worklist.push(n->in(i)); | |
696 } | |
697 } else { | |
698 return false; | |
699 } | |
700 } | |
701 } | |
702 | |
703 // Quit when the worklist is empty, and we've found no offending nodes. | |
704 return true; | |
705 } | |
706 | |
707 //------------------------------Ideal_DU_postCCP------------------------------- | |
708 // Find any cast-away of null-ness and keep its control. Null cast-aways are | |
709 // going away in this pass and we need to make this memory op depend on the | |
710 // gating null check. | |
163 | 711 Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { |
712 return Ideal_common_DU_postCCP(ccp, this, in(MemNode::Address)); | |
713 } | |
0 | 714 |
715 // I tried to leave the CastPP's in. This makes the graph more accurate in | |
716 // some sense; we get to keep around the knowledge that an oop is not-null | |
717 // after some test. Alas, the CastPP's interfere with GVN (some values are | |
718 // the regular oop, some are the CastPP of the oop, all merge at Phi's which | |
719 // cannot collapse, etc). This cost us 10% on SpecJVM, even when I removed | |
720 // some of the more trivial cases in the optimizer. Removing more useless | |
721 // Phi's started allowing Loads to illegally float above null checks. I gave | |
722 // up on this approach. CNC 10/20/2000 | |
163 | 723 // This static method may be called not from MemNode (EncodePNode calls it). |
724 // Only the control edge of the node 'n' might be updated. | |
725 Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) { | |
0 | 726 Node *skipped_cast = NULL; |
727 // Need a null check? Regular static accesses do not because they are | |
728 // from constant addresses. Array ops are gated by the range check (which | |
729 // always includes a NULL check). Just check field ops. | |
163 | 730 if( n->in(MemNode::Control) == NULL ) { |
0 | 731 // Scan upwards for the highest location we can place this memory op. |
732 while( true ) { | |
733 switch( adr->Opcode() ) { | |
734 | |
735 case Op_AddP: // No change to NULL-ness, so peek thru AddP's | |
736 adr = adr->in(AddPNode::Base); | |
737 continue; | |
738 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
739 case Op_DecodeN: // No change to NULL-ness, so peek thru |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
740 case Op_DecodeNKlass: |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
741 adr = adr->in(1); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
742 continue; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
743 |
6139
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
744 case Op_EncodeP: |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
745 case Op_EncodePKlass: |
6139
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
746 // EncodeP node's control edge could be set by this method |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
747 // when EncodeP node depends on CastPP node. |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
748 // |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
749 // Use its control edge for memory op because EncodeP may go away |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
750 // later when it is folded with following or preceding DecodeN node. |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
751 if (adr->in(0) == NULL) { |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
752 // Keep looking for cast nodes. |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
753 adr = adr->in(1); |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
754 continue; |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
755 } |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
756 ccp->hash_delete(n); |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
757 n->set_req(MemNode::Control, adr->in(0)); |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
758 ccp->hash_insert(n); |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
759 return n; |
0919b2e7895d
7174510: 19 JCK compiler tests fail with C2 error: memNode.cpp:812 - ShouldNotReachHere
kvn
parents:
4821
diff
changeset
|
760 |
0 | 761 case Op_CastPP: |
762 // If the CastPP is useless, just peek on through it. | |
763 if( ccp->type(adr) == ccp->type(adr->in(1)) ) { | |
764 // Remember the cast that we've peeked though. If we peek | |
765 // through more than one, then we end up remembering the highest | |
766 // one, that is, if in a loop, the one closest to the top. | |
767 skipped_cast = adr; | |
768 adr = adr->in(1); | |
769 continue; | |
770 } | |
771 // CastPP is going away in this pass! We need this memory op to be | |
772 // control-dependent on the test that is guarding the CastPP. | |
163 | 773 ccp->hash_delete(n); |
774 n->set_req(MemNode::Control, adr->in(0)); | |
775 ccp->hash_insert(n); | |
776 return n; | |
0 | 777 |
778 case Op_Phi: | |
779 // Attempt to float above a Phi to some dominating point. | |
780 if (adr->in(0) != NULL && adr->in(0)->is_CountedLoop()) { | |
781 // If we've already peeked through a Cast (which could have set the | |
782 // control), we can't float above a Phi, because the skipped Cast | |
783 // may not be loop invariant. | |
784 if (adr_phi_is_loop_invariant(adr, skipped_cast)) { | |
785 adr = adr->in(1); | |
786 continue; | |
787 } | |
788 } | |
789 | |
790 // Intentional fallthrough! | |
791 | |
792 // No obvious dominating point. The mem op is pinned below the Phi | |
793 // by the Phi itself. If the Phi goes away (no true value is merged) | |
794 // then the mem op can float, but not indefinitely. It must be pinned | |
795 // behind the controls leading to the Phi. | |
796 case Op_CheckCastPP: | |
797 // These usually stick around to change address type, however a | |
798 // useless one can be elided and we still need to pick up a control edge | |
799 if (adr->in(0) == NULL) { | |
800 // This CheckCastPP node has NO control and is likely useless. But we | |
801 // need check further up the ancestor chain for a control input to keep | |
802 // the node in place. 4959717. | |
803 skipped_cast = adr; | |
804 adr = adr->in(1); | |
805 continue; | |
806 } | |
163 | 807 ccp->hash_delete(n); |
808 n->set_req(MemNode::Control, adr->in(0)); | |
809 ccp->hash_insert(n); | |
810 return n; | |
0 | 811 |
812 // List of "safe" opcodes; those that implicitly block the memory | |
813 // op below any null check. | |
814 case Op_CastX2P: // no null checks on native pointers | |
815 case Op_Parm: // 'this' pointer is not null | |
816 case Op_LoadP: // Loading from within a klass | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
817 case Op_LoadN: // Loading from within a klass |
0 | 818 case Op_LoadKlass: // Loading from within a klass |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
819 case Op_LoadNKlass: // Loading from within a klass |
0 | 820 case Op_ConP: // Loading from a klass |
163 | 821 case Op_ConN: // Loading from a klass |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
822 case Op_ConNKlass: // Loading from a klass |
0 | 823 case Op_CreateEx: // Sucking up the guts of an exception oop |
824 case Op_Con: // Reading from TLS | |
825 case Op_CMoveP: // CMoveP is pinned | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
826 case Op_CMoveN: // CMoveN is pinned |
0 | 827 break; // No progress |
828 | |
829 case Op_Proj: // Direct call to an allocation routine | |
830 case Op_SCMemProj: // Memory state from store conditional ops | |
831 #ifdef ASSERT | |
832 { | |
833 assert(adr->as_Proj()->_con == TypeFunc::Parms, "must be return value"); | |
834 const Node* call = adr->in(0); | |
163 | 835 if (call->is_CallJava()) { |
836 const CallJavaNode* call_java = call->as_CallJava(); | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
837 const TypeTuple *r = call_java->tf()->range(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
838 assert(r->cnt() > TypeFunc::Parms, "must return value"); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
839 const Type* ret_type = r->field_at(TypeFunc::Parms); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
840 assert(ret_type && ret_type->isa_ptr(), "must return pointer"); |
0 | 841 // We further presume that this is one of |
842 // new_instance_Java, new_array_Java, or | |
843 // the like, but do not assert for this. | |
844 } else if (call->is_Allocate()) { | |
845 // similar case to new_instance_Java, etc. | |
846 } else if (!call->is_CallLeaf()) { | |
847 // Projections from fetch_oop (OSR) are allowed as well. | |
848 ShouldNotReachHere(); | |
849 } | |
850 } | |
851 #endif | |
852 break; | |
853 default: | |
854 ShouldNotReachHere(); | |
855 } | |
856 break; | |
857 } | |
858 } | |
859 | |
860 return NULL; // No progress | |
861 } | |
862 | |
863 | |
864 //============================================================================= | |
865 uint LoadNode::size_of() const { return sizeof(*this); } | |
866 uint LoadNode::cmp( const Node &n ) const | |
867 { return !Type::cmp( _type, ((LoadNode&)n)._type ); } | |
868 const Type *LoadNode::bottom_type() const { return _type; } | |
869 uint LoadNode::ideal_reg() const { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
870 return _type->ideal_reg(); |
0 | 871 } |
872 | |
873 #ifndef PRODUCT | |
874 void LoadNode::dump_spec(outputStream *st) const { | |
875 MemNode::dump_spec(st); | |
876 if( !Verbose && !WizardMode ) { | |
877 // standard dump does this in Verbose and WizardMode | |
878 st->print(" #"); _type->dump_on(st); | |
879 } | |
880 } | |
881 #endif | |
882 | |
1609 | 883 #ifdef ASSERT |
884 //----------------------------is_immutable_value------------------------------- | |
885 // Helper function to allow a raw load without control edge for some cases | |
886 bool LoadNode::is_immutable_value(Node* adr) { | |
887 return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() && | |
888 adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal && | |
889 (adr->in(AddPNode::Offset)->find_intptr_t_con(-1) == | |
890 in_bytes(JavaThread::osthread_offset()))); | |
891 } | |
892 #endif | |
0 | 893 |
894 //----------------------------LoadNode::make----------------------------------- | |
895 // Polymorphic factory method: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
896 Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
897 Compile* C = gvn.C; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
898 |
0 | 899 // sanity check the alias category against the created node type |
900 assert(!(adr_type->isa_oopptr() && | |
901 adr_type->offset() == oopDesc::klass_offset_in_bytes()), | |
902 "use LoadKlassNode instead"); | |
903 assert(!(adr_type->isa_aryptr() && | |
904 adr_type->offset() == arrayOopDesc::length_offset_in_bytes()), | |
905 "use LoadRangeNode instead"); | |
1609 | 906 // Check control edge of raw loads |
907 assert( ctl != NULL || C->get_alias_index(adr_type) != Compile::AliasIdxRaw || | |
908 // oop will be recorded in oop map if load crosses safepoint | |
909 rt->isa_oopptr() || is_immutable_value(adr), | |
910 "raw memory operations should have control edge"); | |
0 | 911 switch (bt) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
912 case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
913 case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
914 case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
915 case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
916 case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
917 case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
918 case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
919 case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
920 case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() ); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
921 case T_OBJECT: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
922 #ifdef _LP64 |
163 | 923 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
924 Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop())); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
925 return new (C) DecodeNNode(load, load->bottom_type()->make_ptr()); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
926 } else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
927 #endif |
163 | 928 { |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
929 assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop"); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
930 return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); |
163 | 931 } |
0 | 932 } |
933 ShouldNotReachHere(); | |
934 return (LoadNode*)NULL; | |
935 } | |
936 | |
937 LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt) { | |
938 bool require_atomic = true; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
939 return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), require_atomic); |
0 | 940 } |
941 | |
942 | |
943 | |
944 | |
945 //------------------------------hash------------------------------------------- | |
946 uint LoadNode::hash() const { | |
947 // unroll addition of interesting fields | |
948 return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address); | |
949 } | |
950 | |
951 //---------------------------can_see_stored_value------------------------------ | |
952 // This routine exists to make sure this set of tests is done the same | |
953 // everywhere. We need to make a coordinated change: first LoadNode::Ideal | |
954 // will change the graph shape in a way which makes memory alive twice at the | |
955 // same time (uses the Oracle model of aliasing), then some | |
956 // LoadXNode::Identity will fold things back to the equivalence-class model | |
957 // of aliasing. | |
958 Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { | |
959 Node* ld_adr = in(MemNode::Address); | |
960 | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
961 const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
962 Compile::AliasType* atp = tp != NULL ? phase->C->alias_type(tp) : NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
963 if (EliminateAutoBox && atp != NULL && atp->index() >= Compile::AliasIdxRaw && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
964 atp->field() != NULL && !atp->field()->is_volatile()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
965 uint alias_idx = atp->index(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
966 bool final = atp->field()->is_final(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
967 Node* result = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
968 Node* current = st; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
969 // Skip through chains of MemBarNodes checking the MergeMems for |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
970 // new states for the slice of this load. Stop once any other |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
971 // kind of node is encountered. Loads from final memory can skip |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
972 // through any kind of MemBar but normal loads shouldn't skip |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
973 // through MemBarAcquire since the could allow them to move out of |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
974 // a synchronized region. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
975 while (current->is_Proj()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
976 int opc = current->in(0)->Opcode(); |
3849
f1c12354c3f7
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
3284
diff
changeset
|
977 if ((final && (opc == Op_MemBarAcquire || opc == Op_MemBarAcquireLock)) || |
f1c12354c3f7
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
3284
diff
changeset
|
978 opc == Op_MemBarRelease || opc == Op_MemBarCPUOrder || |
f1c12354c3f7
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
3284
diff
changeset
|
979 opc == Op_MemBarReleaseLock) { |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
980 Node* mem = current->in(0)->in(TypeFunc::Memory); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
981 if (mem->is_MergeMem()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
982 MergeMemNode* merge = mem->as_MergeMem(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
983 Node* new_st = merge->memory_at(alias_idx); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
984 if (new_st == merge->base_memory()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
985 // Keep searching |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
986 current = merge->base_memory(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
987 continue; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
988 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
989 // Save the new memory state for the slice and fall through |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
990 // to exit. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
991 result = new_st; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
992 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
993 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
994 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
995 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
996 if (result != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
997 st = result; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
998 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
999 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1000 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1001 |
0 | 1002 // Loop around twice in the case Load -> Initialize -> Store. |
1003 // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.) | |
1004 for (int trip = 0; trip <= 1; trip++) { | |
1005 | |
1006 if (st->is_Store()) { | |
1007 Node* st_adr = st->in(MemNode::Address); | |
1008 if (!phase->eqv(st_adr, ld_adr)) { | |
1009 // Try harder before giving up... Match raw and non-raw pointers. | |
1010 intptr_t st_off = 0; | |
1011 AllocateNode* alloc = AllocateNode::Ideal_allocation(st_adr, phase, st_off); | |
1012 if (alloc == NULL) return NULL; | |
1013 intptr_t ld_off = 0; | |
1014 AllocateNode* allo2 = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off); | |
1015 if (alloc != allo2) return NULL; | |
1016 if (ld_off != st_off) return NULL; | |
1017 // At this point we have proven something like this setup: | |
1018 // A = Allocate(...) | |
1019 // L = LoadQ(, AddP(CastPP(, A.Parm),, #Off)) | |
1020 // S = StoreQ(, AddP(, A.Parm , #Off), V) | |
1021 // (Actually, we haven't yet proven the Q's are the same.) | |
1022 // In other words, we are loading from a casted version of | |
1023 // the same pointer-and-offset that we stored to. | |
1024 // Thus, we are able to replace L by V. | |
1025 } | |
1026 // Now prove that we have a LoadQ matched to a StoreQ, for some Q. | |
1027 if (store_Opcode() != st->Opcode()) | |
1028 return NULL; | |
1029 return st->in(MemNode::ValueIn); | |
1030 } | |
1031 | |
1032 intptr_t offset = 0; // scratch | |
1033 | |
1034 // A load from a freshly-created object always returns zero. | |
1035 // (This can happen after LoadNode::Ideal resets the load's memory input | |
1036 // to find_captured_store, which returned InitializeNode::zero_memory.) | |
1037 if (st->is_Proj() && st->in(0)->is_Allocate() && | |
1038 st->in(0) == AllocateNode::Ideal_allocation(ld_adr, phase, offset) && | |
1039 offset >= st->in(0)->as_Allocate()->minimum_header_size()) { | |
1040 // return a zero value for the load's basic type | |
1041 // (This is one of the few places where a generic PhaseTransform | |
1042 // can create new nodes. Think of it as lazily manifesting | |
1043 // virtually pre-existing constants.) | |
1044 return phase->zerocon(memory_type()); | |
1045 } | |
1046 | |
1047 // A load from an initialization barrier can match a captured store. | |
1048 if (st->is_Proj() && st->in(0)->is_Initialize()) { | |
1049 InitializeNode* init = st->in(0)->as_Initialize(); | |
1050 AllocateNode* alloc = init->allocation(); | |
1051 if (alloc != NULL && | |
1052 alloc == AllocateNode::Ideal_allocation(ld_adr, phase, offset)) { | |
1053 // examine a captured store value | |
1054 st = init->find_captured_store(offset, memory_size(), phase); | |
1055 if (st != NULL) | |
1056 continue; // take one more trip around | |
1057 } | |
1058 } | |
1059 | |
1060 break; | |
1061 } | |
1062 | |
1063 return NULL; | |
1064 } | |
1065 | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1066 //----------------------is_instance_field_load_with_local_phi------------------ |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1067 bool LoadNode::is_instance_field_load_with_local_phi(Node* ctrl) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1068 if( in(MemNode::Memory)->is_Phi() && in(MemNode::Memory)->in(0) == ctrl && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1069 in(MemNode::Address)->is_AddP() ) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1070 const TypeOopPtr* t_oop = in(MemNode::Address)->bottom_type()->isa_oopptr(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1071 // Only instances. |
223 | 1072 if( t_oop != NULL && t_oop->is_known_instance_field() && |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1073 t_oop->offset() != Type::OffsetBot && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1074 t_oop->offset() != Type::OffsetTop) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1075 return true; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1076 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1077 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1078 return false; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1079 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1080 |
0 | 1081 //------------------------------Identity--------------------------------------- |
1082 // Loads are identity if previous store is to same address | |
1083 Node *LoadNode::Identity( PhaseTransform *phase ) { | |
1084 // If the previous store-maker is the right kind of Store, and the store is | |
1085 // to the same address, then we are equal to the value stored. | |
1086 Node* mem = in(MemNode::Memory); | |
1087 Node* value = can_see_stored_value(mem, phase); | |
1088 if( value ) { | |
1089 // byte, short & char stores truncate naturally. | |
1090 // A load has to load the truncated value which requires | |
1091 // some sort of masking operation and that requires an | |
1092 // Ideal call instead of an Identity call. | |
1093 if (memory_size() < BytesPerInt) { | |
1094 // If the input to the store does not fit with the load's result type, | |
1095 // it must be truncated via an Ideal call. | |
1096 if (!phase->type(value)->higher_equal(phase->type(this))) | |
1097 return this; | |
1098 } | |
1099 // (This works even when value is a Con, but LoadNode::Value | |
1100 // usually runs first, producing the singleton type of the Con.) | |
1101 return value; | |
1102 } | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1103 |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1104 // Search for an existing data phi which was generated before for the same |
605 | 1105 // instance's field to avoid infinite generation of phis in a loop. |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1106 Node *region = mem->in(0); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1107 if (is_instance_field_load_with_local_phi(region)) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1108 const TypePtr *addr_t = in(MemNode::Address)->bottom_type()->isa_ptr(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1109 int this_index = phase->C->get_alias_index(addr_t); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1110 int this_offset = addr_t->offset(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1111 int this_id = addr_t->is_oopptr()->instance_id(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1112 const Type* this_type = bottom_type(); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1113 for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1114 Node* phi = region->fast_out(i); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1115 if (phi->is_Phi() && phi != mem && |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1116 phi->as_Phi()->is_same_inst_field(this_type, this_id, this_index, this_offset)) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1117 return phi; |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1118 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1119 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1120 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1121 |
0 | 1122 return this; |
1123 } | |
1124 | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1125 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1126 // Returns true if the AliasType refers to the field that holds the |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1127 // cached box array. Currently only handles the IntegerCache case. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1128 static bool is_autobox_cache(Compile::AliasType* atp) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1129 if (atp != NULL && atp->field() != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1130 ciField* field = atp->field(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1131 ciSymbol* klass = field->holder()->name(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1132 if (field->name() == ciSymbol::cache_field_name() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1133 field->holder()->uses_default_loader() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1134 klass == ciSymbol::java_lang_Integer_IntegerCache()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1135 return true; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1136 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1137 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1138 return false; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1139 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1140 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1141 // Fetch the base value in the autobox array |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1142 static bool fetch_autobox_base(Compile::AliasType* atp, int& cache_offset) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1143 if (atp != NULL && atp->field() != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1144 ciField* field = atp->field(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1145 ciSymbol* klass = field->holder()->name(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1146 if (field->name() == ciSymbol::cache_field_name() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1147 field->holder()->uses_default_loader() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1148 klass == ciSymbol::java_lang_Integer_IntegerCache()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1149 assert(field->is_constant(), "what?"); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1150 ciObjArray* array = field->constant_value().as_object()->as_obj_array(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1151 // Fetch the box object at the base of the array and get its value |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1152 ciInstance* box = array->obj_at(0)->as_instance(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1153 ciInstanceKlass* ik = box->klass()->as_instance_klass(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1154 if (ik->nof_nonstatic_fields() == 1) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1155 // This should be true nonstatic_field_at requires calling |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1156 // nof_nonstatic_fields so check it anyway |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1157 ciConstant c = box->field_value(ik->nonstatic_field_at(0)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1158 cache_offset = c.as_int(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1159 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1160 return true; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1161 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1162 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1163 return false; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1164 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1165 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1166 // Returns true if the AliasType refers to the value field of an |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1167 // autobox object. Currently only handles Integer. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1168 static bool is_autobox_object(Compile::AliasType* atp) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1169 if (atp != NULL && atp->field() != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1170 ciField* field = atp->field(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1171 ciSymbol* klass = field->holder()->name(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1172 if (field->name() == ciSymbol::value_name() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1173 field->holder()->uses_default_loader() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1174 klass == ciSymbol::java_lang_Integer()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1175 return true; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1176 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1177 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1178 return false; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1179 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1180 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1181 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1182 // We're loading from an object which has autobox behaviour. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1183 // If this object is result of a valueOf call we'll have a phi |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1184 // merging a newly allocated object and a load from the cache. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1185 // We want to replace this load with the original incoming |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1186 // argument to the valueOf call. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1187 Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1188 Node* base = in(Address)->in(AddPNode::Base); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1189 if (base->is_Phi() && base->req() == 3) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1190 AllocateNode* allocation = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1191 int allocation_index = -1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1192 int load_index = -1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1193 for (uint i = 1; i < base->req(); i++) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1194 allocation = AllocateNode::Ideal_allocation(base->in(i), phase); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1195 if (allocation != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1196 allocation_index = i; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1197 load_index = 3 - allocation_index; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1198 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1199 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1200 } |
583
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1201 bool has_load = ( allocation != NULL && |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1202 (base->in(load_index)->is_Load() || |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1203 base->in(load_index)->is_DecodeN() && |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1204 base->in(load_index)->in(1)->is_Load()) ); |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1205 if (has_load && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) { |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1206 // Push the loads from the phi that comes from valueOf up |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1207 // through it to allow elimination of the loads and the recovery |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1208 // of the original value. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1209 Node* mem_phi = in(Memory); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1210 Node* offset = in(Address)->in(AddPNode::Offset); |
553 | 1211 Node* region = base->in(0); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1212 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1213 Node* in1 = clone(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1214 Node* in1_addr = in1->in(Address)->clone(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1215 in1_addr->set_req(AddPNode::Base, base->in(allocation_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1216 in1_addr->set_req(AddPNode::Address, base->in(allocation_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1217 in1_addr->set_req(AddPNode::Offset, offset); |
553 | 1218 in1->set_req(0, region->in(allocation_index)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1219 in1->set_req(Address, in1_addr); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1220 in1->set_req(Memory, mem_phi->in(allocation_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1221 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1222 Node* in2 = clone(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1223 Node* in2_addr = in2->in(Address)->clone(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1224 in2_addr->set_req(AddPNode::Base, base->in(load_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1225 in2_addr->set_req(AddPNode::Address, base->in(load_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1226 in2_addr->set_req(AddPNode::Offset, offset); |
553 | 1227 in2->set_req(0, region->in(load_index)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1228 in2->set_req(Address, in2_addr); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1229 in2->set_req(Memory, mem_phi->in(load_index)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1230 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1231 in1_addr = phase->transform(in1_addr); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1232 in1 = phase->transform(in1); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1233 in2_addr = phase->transform(in2_addr); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1234 in2 = phase->transform(in2); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1235 |
553 | 1236 PhiNode* result = PhiNode::make_blank(region, this); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1237 result->set_req(allocation_index, in1); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1238 result->set_req(load_index, in2); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1239 return result; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1240 } |
583
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1241 } else if (base->is_Load() || |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1242 base->is_DecodeN() && base->in(1)->is_Load()) { |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1243 if (base->is_DecodeN()) { |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1244 // Get LoadN node which loads cached Integer object |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1245 base = base->in(1); |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1246 } |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1247 // Eliminate the load of Integer.value for integers from the cache |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1248 // array by deriving the value from the index into the array. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1249 // Capture the offset of the load and then reverse the computation. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1250 Node* load_base = base->in(Address)->in(AddPNode::Base); |
583
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1251 if (load_base->is_DecodeN()) { |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1252 // Get LoadN node which loads IntegerCache.cache field |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1253 load_base = load_base->in(1); |
5d75ab5f6698
6807084: AutoBox elimination is broken with compressed oops
kvn
parents:
570
diff
changeset
|
1254 } |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1255 if (load_base != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1256 Compile::AliasType* atp = phase->C->alias_type(load_base->adr_type()); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1257 intptr_t cache_offset; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1258 int shift = -1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1259 Node* cache = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1260 if (is_autobox_cache(atp)) { |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
17
diff
changeset
|
1261 shift = exact_log2(type2aelembytes(T_OBJECT)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1262 cache = AddPNode::Ideal_base_and_offset(load_base->in(Address), phase, cache_offset); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1263 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1264 if (cache != NULL && base->in(Address)->is_AddP()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1265 Node* elements[4]; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1266 int count = base->in(Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1267 int cache_low; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1268 if (count > 0 && fetch_autobox_base(atp, cache_low)) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1269 int offset = arrayOopDesc::base_offset_in_bytes(memory_type()) - (cache_low << shift); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1270 // Add up all the offsets making of the address of the load |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1271 Node* result = elements[0]; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1272 for (int i = 1; i < count; i++) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1273 result = phase->transform(new (phase->C) AddXNode(result, elements[i])); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1274 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1275 // Remove the constant offset from the address and then |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1276 // remove the scaling of the offset to recover the original index. |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1277 result = phase->transform(new (phase->C) AddXNode(result, phase->MakeConX(-offset))); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1278 if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1279 // Peel the shift off directly but wrap it in a dummy node |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1280 // since Ideal can't return existing nodes |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1281 result = new (phase->C) RShiftXNode(result->in(1), phase->intcon(0)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1282 } else { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1283 result = new (phase->C) RShiftXNode(result, phase->intcon(shift)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1284 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1285 #ifdef _LP64 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1286 result = new (phase->C) ConvL2INode(phase->transform(result)); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1287 #endif |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1288 return result; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1289 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1290 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1291 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1292 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1293 return NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1294 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1295 |
163 | 1296 //------------------------------split_through_phi------------------------------ |
1297 // Split instance field load through Phi. | |
1298 Node *LoadNode::split_through_phi(PhaseGVN *phase) { | |
1299 Node* mem = in(MemNode::Memory); | |
1300 Node* address = in(MemNode::Address); | |
1301 const TypePtr *addr_t = phase->type(address)->isa_ptr(); | |
1302 const TypeOopPtr *t_oop = addr_t->isa_oopptr(); | |
1303 | |
1304 assert(mem->is_Phi() && (t_oop != NULL) && | |
223 | 1305 t_oop->is_known_instance_field(), "invalide conditions"); |
163 | 1306 |
1307 Node *region = mem->in(0); | |
1308 if (region == NULL) { | |
1309 return NULL; // Wait stable graph | |
1310 } | |
1311 uint cnt = mem->req(); | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1312 for (uint i = 1; i < cnt; i++) { |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1313 Node* rc = region->in(i); |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1314 if (rc == NULL || phase->type(rc) == Type::TOP) |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1315 return NULL; // Wait stable graph |
163 | 1316 Node *in = mem->in(i); |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1317 if (in == NULL) { |
163 | 1318 return NULL; // Wait stable graph |
1319 } | |
1320 } | |
1321 // Check for loop invariant. | |
1322 if (cnt == 3) { | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1323 for (uint i = 1; i < cnt; i++) { |
163 | 1324 Node *in = mem->in(i); |
1325 Node* m = MemNode::optimize_memory_chain(in, addr_t, phase); | |
1326 if (m == mem) { | |
1327 set_req(MemNode::Memory, mem->in(cnt - i)); // Skip this phi. | |
1328 return this; | |
1329 } | |
1330 } | |
1331 } | |
1332 // Split through Phi (see original code in loopopts.cpp). | |
1333 assert(phase->C->have_alias_type(addr_t), "instance should have alias type"); | |
1334 | |
1335 // Do nothing here if Identity will find a value | |
1336 // (to avoid infinite chain of value phis generation). | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1337 if (!phase->eqv(this, this->Identity(phase))) |
163 | 1338 return NULL; |
1339 | |
1340 // Skip the split if the region dominates some control edge of the address. | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1341 if (!MemNode::all_controls_dominate(address, region)) |
163 | 1342 return NULL; |
1343 | |
1344 const Type* this_type = this->bottom_type(); | |
1345 int this_index = phase->C->get_alias_index(addr_t); | |
1346 int this_offset = addr_t->offset(); | |
1347 int this_iid = addr_t->is_oopptr()->instance_id(); | |
1348 PhaseIterGVN *igvn = phase->is_IterGVN(); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1349 Node *phi = new (igvn->C) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset); |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1350 for (uint i = 1; i < region->req(); i++) { |
163 | 1351 Node *x; |
1352 Node* the_clone = NULL; | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1353 if (region->in(i) == phase->C->top()) { |
163 | 1354 x = phase->C->top(); // Dead path? Use a dead data op |
1355 } else { | |
1356 x = this->clone(); // Else clone up the data op | |
1357 the_clone = x; // Remember for possible deletion. | |
1358 // Alter data node to use pre-phi inputs | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1359 if (this->in(0) == region) { |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1360 x->set_req(0, region->in(i)); |
163 | 1361 } else { |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1362 x->set_req(0, NULL); |
163 | 1363 } |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1364 for (uint j = 1; j < this->req(); j++) { |
163 | 1365 Node *in = this->in(j); |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1366 if (in->is_Phi() && in->in(0) == region) |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1367 x->set_req(j, in->in(i)); // Use pre-Phi input for the clone |
163 | 1368 } |
1369 } | |
1370 // Check for a 'win' on some paths | |
1371 const Type *t = x->Value(igvn); | |
1372 | |
1373 bool singleton = t->singleton(); | |
1374 | |
1375 // See comments in PhaseIdealLoop::split_thru_phi(). | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1376 if (singleton && t == Type::TOP) { |
163 | 1377 singleton &= region->is_Loop() && (i != LoopNode::EntryControl); |
1378 } | |
1379 | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1380 if (singleton) { |
163 | 1381 x = igvn->makecon(t); |
1382 } else { | |
1383 // We now call Identity to try to simplify the cloned node. | |
1384 // Note that some Identity methods call phase->type(this). | |
1385 // Make sure that the type array is big enough for | |
1386 // our new node, even though we may throw the node away. | |
1387 // (This tweaking with igvn only works because x is a new node.) | |
1388 igvn->set_type(x, t); | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
1389 // If x is a TypeNode, capture any more-precise type permanently into Node |
605 | 1390 // otherwise it will be not updated during igvn->transform since |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
1391 // igvn->type(x) is set to x->Value() already. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
1392 x->raise_bottom_type(t); |
163 | 1393 Node *y = x->Identity(igvn); |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1394 if (y != x) { |
163 | 1395 x = y; |
1396 } else { | |
1397 y = igvn->hash_find(x); | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1398 if (y) { |
163 | 1399 x = y; |
1400 } else { | |
1401 // Else x is a new node we are keeping | |
1402 // We do not need register_new_node_with_optimizer | |
1403 // because set_type has already been called. | |
1404 igvn->_worklist.push(x); | |
1405 } | |
1406 } | |
1407 } | |
1408 if (x != the_clone && the_clone != NULL) | |
1409 igvn->remove_dead_node(the_clone); | |
1410 phi->set_req(i, x); | |
1411 } | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1412 // Record Phi |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1413 igvn->register_new_node_with_optimizer(phi); |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1414 return phi; |
163 | 1415 } |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1416 |
0 | 1417 //------------------------------Ideal------------------------------------------ |
1418 // If the load is from Field memory and the pointer is non-null, we can | |
1419 // zero out the control input. | |
1420 // If the offset is constant and the base is an object allocation, | |
1421 // try to hook me up to the exact initializing store. | |
1422 Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1423 Node* p = MemNode::Ideal_common(phase, can_reshape); | |
1424 if (p) return (p == NodeSentinel) ? NULL : p; | |
1425 | |
1426 Node* ctrl = in(MemNode::Control); | |
1427 Node* address = in(MemNode::Address); | |
1428 | |
1429 // Skip up past a SafePoint control. Cannot do this for Stores because | |
1430 // pointer stores & cardmarks must stay on the same side of a SafePoint. | |
1431 if( ctrl != NULL && ctrl->Opcode() == Op_SafePoint && | |
1432 phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw ) { | |
1433 ctrl = ctrl->in(0); | |
1434 set_req(MemNode::Control,ctrl); | |
1435 } | |
1436 | |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1437 intptr_t ignore = 0; |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1438 Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1439 if (base != NULL |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1440 && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw) { |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1441 // Check for useless control edge in some common special cases |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1442 if (in(MemNode::Control) != NULL |
0 | 1443 && phase->type(base)->higher_equal(TypePtr::NOTNULL) |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
1444 && all_controls_dominate(base, phase->C->start())) { |
0 | 1445 // A method-invariant, non-null address (constant or 'this' argument). |
1446 set_req(MemNode::Control, NULL); | |
1447 } | |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1448 |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1449 if (EliminateAutoBox && can_reshape) { |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1450 assert(!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "the autobox pointer should be non-null"); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1451 Compile::AliasType* atp = phase->C->alias_type(adr_type()); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1452 if (is_autobox_object(atp)) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1453 Node* result = eliminate_autobox(phase); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1454 if (result != NULL) return result; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1455 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1456 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1457 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1458 |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1459 Node* mem = in(MemNode::Memory); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1460 const TypePtr *addr_t = phase->type(address)->isa_ptr(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1461 |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1462 if (addr_t != NULL) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1463 // try to optimize our memory input |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1464 Node* opt_mem = MemNode::optimize_memory_chain(mem, addr_t, phase); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1465 if (opt_mem != mem) { |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1466 set_req(MemNode::Memory, opt_mem); |
305 | 1467 if (phase->type( opt_mem ) == Type::TOP) return NULL; |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1468 return this; |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1469 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1470 const TypeOopPtr *t_oop = addr_t->isa_oopptr(); |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1471 if (can_reshape && opt_mem->is_Phi() && |
223 | 1472 (t_oop != NULL) && t_oop->is_known_instance_field()) { |
4064
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1473 PhaseIterGVN *igvn = phase->is_IterGVN(); |
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1474 if (igvn != NULL && igvn->_worklist.member(opt_mem)) { |
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1475 // Delay this transformation until memory Phi is processed. |
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1476 phase->is_IterGVN()->_worklist.push(this); |
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1477 return NULL; |
670a74b863fc
7107042: assert(no_dead_loop) failed: dead loop detected
kvn
parents:
3961
diff
changeset
|
1478 } |
163 | 1479 // Split instance field load through Phi. |
1480 Node* result = split_through_phi(phase); | |
1481 if (result != NULL) return result; | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1482 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1483 } |
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
68
diff
changeset
|
1484 |
0 | 1485 // Check for prior store with a different base or offset; make Load |
1486 // independent. Skip through any number of them. Bail out if the stores | |
1487 // are in an endless dead cycle and report no progress. This is a key | |
1488 // transform for Reflection. However, if after skipping through the Stores | |
1489 // we can't then fold up against a prior store do NOT do the transform as | |
1490 // this amounts to using the 'Oracle' model of aliasing. It leaves the same | |
1491 // array memory alive twice: once for the hoisted Load and again after the | |
1492 // bypassed Store. This situation only works if EVERYBODY who does | |
1493 // anti-dependence work knows how to bypass. I.e. we need all | |
1494 // anti-dependence checks to ask the same Oracle. Right now, that Oracle is | |
1495 // the alias index stuff. So instead, peek through Stores and IFF we can | |
1496 // fold up, do so. | |
1497 Node* prev_mem = find_previous_store(phase); | |
1498 // Steps (a), (b): Walk past independent stores to find an exact match. | |
1499 if (prev_mem != NULL && prev_mem != in(MemNode::Memory)) { | |
1500 // (c) See if we can fold up on the spot, but don't fold up here. | |
558
3b5ac9e7e6ea
6796746: rename LoadC (char) opcode class to LoadUS (unsigned short)
twisti
parents:
553
diff
changeset
|
1501 // Fold-up might require truncation (for LoadB/LoadS/LoadUS) or |
0 | 1502 // just return a prior value, which is done by Identity calls. |
1503 if (can_see_stored_value(prev_mem, phase)) { | |
1504 // Make ready for step (d): | |
1505 set_req(MemNode::Memory, prev_mem); | |
1506 return this; | |
1507 } | |
1508 } | |
1509 | |
1510 return NULL; // No further progress | |
1511 } | |
1512 | |
1513 // Helper to recognize certain Klass fields which are invariant across | |
1514 // some group of array types (e.g., int[] or all T[] where T < Object). | |
1515 const Type* | |
1516 LoadNode::load_array_final_field(const TypeKlassPtr *tkls, | |
1517 ciKlass* klass) const { | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1518 if (tkls->offset() == in_bytes(Klass::modifier_flags_offset())) { |
0 | 1519 // The field is Klass::_modifier_flags. Return its (constant) value. |
1520 // (Folds up the 2nd indirection in aClassConstant.getModifiers().) | |
1521 assert(this->Opcode() == Op_LoadI, "must load an int from _modifier_flags"); | |
1522 return TypeInt::make(klass->modifier_flags()); | |
1523 } | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1524 if (tkls->offset() == in_bytes(Klass::access_flags_offset())) { |
0 | 1525 // The field is Klass::_access_flags. Return its (constant) value. |
1526 // (Folds up the 2nd indirection in Reflection.getClassAccessFlags(aClassConstant).) | |
1527 assert(this->Opcode() == Op_LoadI, "must load an int from _access_flags"); | |
1528 return TypeInt::make(klass->access_flags()); | |
1529 } | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1530 if (tkls->offset() == in_bytes(Klass::layout_helper_offset())) { |
0 | 1531 // The field is Klass::_layout_helper. Return its constant value if known. |
1532 assert(this->Opcode() == Op_LoadI, "must load an int from _layout_helper"); | |
1533 return TypeInt::make(klass->layout_helper()); | |
1534 } | |
1535 | |
1536 // No match. | |
1537 return NULL; | |
1538 } | |
1539 | |
1540 //------------------------------Value----------------------------------------- | |
1541 const Type *LoadNode::Value( PhaseTransform *phase ) const { | |
1542 // Either input is TOP ==> the result is TOP | |
1543 Node* mem = in(MemNode::Memory); | |
1544 const Type *t1 = phase->type(mem); | |
1545 if (t1 == Type::TOP) return Type::TOP; | |
1546 Node* adr = in(MemNode::Address); | |
1547 const TypePtr* tp = phase->type(adr)->isa_ptr(); | |
1548 if (tp == NULL || tp->empty()) return Type::TOP; | |
1549 int off = tp->offset(); | |
1550 assert(off != Type::OffsetTop, "case covered by TypePtr::empty"); | |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1551 Compile* C = phase->C; |
0 | 1552 |
1553 // Try to guess loaded type from pointer type | |
1554 if (tp->base() == Type::AryPtr) { | |
1555 const Type *t = tp->is_aryptr()->elem(); | |
1556 // Don't do this for integer types. There is only potential profit if | |
1557 // the element type t is lower than _type; that is, for int types, if _type is | |
1558 // more restrictive than t. This only happens here if one is short and the other | |
1559 // char (both 16 bits), and in those cases we've made an intentional decision | |
1560 // to use one kind of load over the other. See AndINode::Ideal and 4965907. | |
1561 // Also, do not try to narrow the type for a LoadKlass, regardless of offset. | |
1562 // | |
1563 // Yes, it is possible to encounter an expression like (LoadKlass p1:(AddP x x 8)) | |
1564 // where the _gvn.type of the AddP is wider than 8. This occurs when an earlier | |
1565 // copy p0 of (AddP x x 8) has been proven equal to p1, and the p0 has been | |
1566 // subsumed by p1. If p1 is on the worklist but has not yet been re-transformed, | |
1567 // it is possible that p1 will have a type like Foo*[int+]:NotNull*+any. | |
1568 // In fact, that could have been the original type of p1, and p1 could have | |
1569 // had an original form like p1:(AddP x x (LShiftL quux 3)), where the | |
1570 // expression (LShiftL quux 3) independently optimized to the constant 8. | |
1571 if ((t->isa_int() == NULL) && (t->isa_long() == NULL) | |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
6139
diff
changeset
|
1572 && (_type->isa_vect() == NULL) |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
253
diff
changeset
|
1573 && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) { |
0 | 1574 // t might actually be lower than _type, if _type is a unique |
1575 // concrete subclass of abstract class t. | |
1576 // Make sure the reference is not into the header, by comparing | |
1577 // the offset against the offset of the start of the array's data. | |
1578 // Different array types begin at slightly different offsets (12 vs. 16). | |
1579 // We choose T_BYTE as an example base type that is least restrictive | |
1580 // as to alignment, which will therefore produce the smallest | |
1581 // possible base offset. | |
1582 const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE); | |
1583 if ((uint)off >= (uint)min_base_off) { // is the offset beyond the header? | |
1584 const Type* jt = t->join(_type); | |
1585 // In any case, do not allow the join, per se, to empty out the type. | |
1586 if (jt->empty() && !t->empty()) { | |
1587 // This can happen if a interface-typed array narrows to a class type. | |
1588 jt = _type; | |
1589 } | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1590 |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1591 if (EliminateAutoBox && adr->is_AddP()) { |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1592 // The pointers in the autobox arrays are always non-null |
708
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1593 Node* base = adr->in(AddPNode::Base); |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1594 if (base != NULL && |
f2049ae95c3d
6711117: Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
kvn
parents:
681
diff
changeset
|
1595 !phase->type(base)->higher_equal(TypePtr::NULL_PTR)) { |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1596 Compile::AliasType* atp = C->alias_type(base->adr_type()); |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1597 if (is_autobox_cache(atp)) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1598 return jt->join(TypePtr::NOTNULL)->is_ptr(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1599 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1600 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
1601 } |
0 | 1602 return jt; |
1603 } | |
1604 } | |
1605 } else if (tp->base() == Type::InstPtr) { | |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1606 ciEnv* env = C->env(); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1607 const TypeInstPtr* tinst = tp->is_instptr(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1608 ciKlass* klass = tinst->klass(); |
0 | 1609 assert( off != Type::OffsetBot || |
1610 // arrays can be cast to Objects | |
1611 tp->is_oopptr()->klass()->is_java_lang_Object() || | |
1612 // unsafe field access may not have a constant offset | |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1613 C->has_unsafe_access(), |
0 | 1614 "Field accesses must be precise" ); |
1615 // For oop loads, we expect the _type to be precise | |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1616 if (klass == env->String_klass() && |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1617 adr->is_AddP() && off != Type::OffsetBot) { |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1618 // For constant Strings treat the final fields as compile time constants. |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1619 Node* base = adr->in(AddPNode::Base); |
1766
02f0a9b6f654
6969586: OptimizeStringConcat: SIGSEGV in LoadNode::Value()
never
parents:
1609
diff
changeset
|
1620 const TypeOopPtr* t = phase->type(base)->isa_oopptr(); |
02f0a9b6f654
6969586: OptimizeStringConcat: SIGSEGV in LoadNode::Value()
never
parents:
1609
diff
changeset
|
1621 if (t != NULL && t->singleton()) { |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1622 ciField* field = env->String_klass()->get_field_by_offset(off, false); |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1623 if (field != NULL && field->is_final()) { |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1624 ciObject* string = t->const_oop(); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1625 ciConstant constant = string->as_instance()->field_value(field); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1626 if (constant.basic_type() == T_INT) { |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1627 return TypeInt::make(constant.as_int()); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1628 } else if (constant.basic_type() == T_ARRAY) { |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1629 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
2379
b099aaf51bf8
6962931: move interned strings out of the perm gen
jcoomes
parents:
2320
diff
changeset
|
1630 return TypeNarrowOop::make_from_constant(constant.as_object(), true); |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1631 } else { |
2379
b099aaf51bf8
6962931: move interned strings out of the perm gen
jcoomes
parents:
2320
diff
changeset
|
1632 return TypeOopPtr::make_from_constant(constant.as_object(), true); |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
2317
diff
changeset
|
1633 } |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1634 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1635 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1636 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1062
diff
changeset
|
1637 } |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1638 // Optimizations for constant objects |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1639 ciObject* const_oop = tinst->const_oop(); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1640 if (const_oop != NULL) { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1641 // For constant CallSites treat the target field as a compile time constant. |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1642 if (const_oop->is_call_site()) { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1643 ciCallSite* call_site = const_oop->as_call_site(); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1644 ciField* field = call_site->klass()->as_instance_klass()->get_field_by_offset(off, /*is_static=*/ false); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1645 if (field != NULL && field->is_call_site_target()) { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1646 ciMethodHandle* target = call_site->get_target(); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1647 if (target != NULL) { // just in case |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1648 ciConstant constant(T_OBJECT, target); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1649 const Type* t; |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1650 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1651 t = TypeNarrowOop::make_from_constant(constant.as_object(), true); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1652 } else { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1653 t = TypeOopPtr::make_from_constant(constant.as_object(), true); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1654 } |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1655 // Add a dependence for invalidation of the optimization. |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1656 if (!call_site->is_constant_call_site()) { |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1657 C->dependencies()->assert_call_site_target_value(call_site, target); |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1658 } |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1659 return t; |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1660 } |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1661 } |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1662 } |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3849
diff
changeset
|
1663 } |
0 | 1664 } else if (tp->base() == Type::KlassPtr) { |
1665 assert( off != Type::OffsetBot || | |
1666 // arrays can be cast to Objects | |
1667 tp->is_klassptr()->klass()->is_java_lang_Object() || | |
1668 // also allow array-loading from the primary supertype | |
1669 // array during subtype checks | |
1670 Opcode() == Op_LoadKlass, | |
1671 "Field accesses must be precise" ); | |
1672 // For klass/static loads, we expect the _type to be precise | |
1673 } | |
1674 | |
1675 const TypeKlassPtr *tkls = tp->isa_klassptr(); | |
1676 if (tkls != NULL && !StressReflectiveCode) { | |
1677 ciKlass* klass = tkls->klass(); | |
1678 if (klass->is_loaded() && tkls->klass_is_exact()) { | |
1679 // We are loading a field from a Klass metaobject whose identity | |
1680 // is known at compile time (the type is "exact" or "precise"). | |
1681 // Check for fields we know are maintained as constants by the VM. | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1682 if (tkls->offset() == in_bytes(Klass::super_check_offset_offset())) { |
0 | 1683 // The field is Klass::_super_check_offset. Return its (constant) value. |
1684 // (Folds up type checking code.) | |
1685 assert(Opcode() == Op_LoadI, "must load an int from _super_check_offset"); | |
1686 return TypeInt::make(klass->super_check_offset()); | |
1687 } | |
1688 // Compute index into primary_supers array | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1689 juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*); |
0 | 1690 // Check for overflowing; use unsigned compare to handle the negative case. |
1691 if( depth < ciKlass::primary_super_limit() ) { | |
1692 // The field is an element of Klass::_primary_supers. Return its (constant) value. | |
1693 // (Folds up type checking code.) | |
1694 assert(Opcode() == Op_LoadKlass, "must load a klass from _primary_supers"); | |
1695 ciKlass *ss = klass->super_of_depth(depth); | |
1696 return ss ? TypeKlassPtr::make(ss) : TypePtr::NULL_PTR; | |
1697 } | |
1698 const Type* aift = load_array_final_field(tkls, klass); | |
1699 if (aift != NULL) return aift; | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
1700 if (tkls->offset() == in_bytes(ArrayKlass::component_mirror_offset()) |
0 | 1701 && klass->is_array_klass()) { |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
1702 // The field is ArrayKlass::_component_mirror. Return its (constant) value. |
0 | 1703 // (Folds up aClassConstant.getComponentType, common in Arrays.copyOf.) |
1704 assert(Opcode() == Op_LoadP, "must load an oop from _component_mirror"); | |
1705 return TypeInstPtr::make(klass->as_array_klass()->component_mirror()); | |
1706 } | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1707 if (tkls->offset() == in_bytes(Klass::java_mirror_offset())) { |
0 | 1708 // The field is Klass::_java_mirror. Return its (constant) value. |
1709 // (Folds up the 2nd indirection in anObjConstant.getClass().) | |
1710 assert(Opcode() == Op_LoadP, "must load an oop from _java_mirror"); | |
1711 return TypeInstPtr::make(klass->java_mirror()); | |
1712 } | |
1713 } | |
1714 | |
1715 // We can still check if we are loading from the primary_supers array at a | |
1716 // shallow enough depth. Even though the klass is not exact, entries less | |
1717 // than or equal to its super depth are correct. | |
1718 if (klass->is_loaded() ) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1719 ciType *inner = klass; |
0 | 1720 while( inner->is_obj_array_klass() ) |
1721 inner = inner->as_obj_array_klass()->base_element_type(); | |
1722 if( inner->is_instance_klass() && | |
1723 !inner->as_instance_klass()->flags().is_interface() ) { | |
1724 // Compute index into primary_supers array | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1725 juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*); |
0 | 1726 // Check for overflowing; use unsigned compare to handle the negative case. |
1727 if( depth < ciKlass::primary_super_limit() && | |
1728 depth <= klass->super_depth() ) { // allow self-depth checks to handle self-check case | |
1729 // The field is an element of Klass::_primary_supers. Return its (constant) value. | |
1730 // (Folds up type checking code.) | |
1731 assert(Opcode() == Op_LoadKlass, "must load a klass from _primary_supers"); | |
1732 ciKlass *ss = klass->super_of_depth(depth); | |
1733 return ss ? TypeKlassPtr::make(ss) : TypePtr::NULL_PTR; | |
1734 } | |
1735 } | |
1736 } | |
1737 | |
1738 // If the type is enough to determine that the thing is not an array, | |
1739 // we can give the layout_helper a positive interval type. | |
1740 // This will help short-circuit some reflective code. | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
1741 if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) |
0 | 1742 && !klass->is_array_klass() // not directly typed as an array |
1743 && !klass->is_interface() // specifically not Serializable & Cloneable | |
1744 && !klass->is_java_lang_Object() // not the supertype of all T[] | |
1745 ) { | |
1746 // Note: When interfaces are reliable, we can narrow the interface | |
1747 // test to (klass != Serializable && klass != Cloneable). | |
1748 assert(Opcode() == Op_LoadI, "must load an int from _layout_helper"); | |
1749 jint min_size = Klass::instance_layout_helper(oopDesc::header_size(), false); | |
1750 // The key property of this type is that it folds up tests | |
1751 // for array-ness, since it proves that the layout_helper is positive. | |
1752 // Thus, a generic value like the basic object layout helper works fine. | |
1753 return TypeInt::make(min_size, max_jint, Type::WidenMin); | |
1754 } | |
1755 } | |
1756 | |
1757 // If we are loading from a freshly-allocated object, produce a zero, | |
1758 // if the load is provably beyond the header of the object. | |
1759 // (Also allow a variable load from a fresh array to produce zero.) | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1760 const TypeOopPtr *tinst = tp->isa_oopptr(); |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1761 bool is_instance = (tinst != NULL) && tinst->is_known_instance_field(); |
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1762 if (ReduceFieldZeroing || is_instance) { |
0 | 1763 Node* value = can_see_stored_value(mem,phase); |
4815 | 1764 if (value != NULL && value->is_Con()) { |
1765 assert(value->bottom_type()->higher_equal(_type),"sanity"); | |
0 | 1766 return value->bottom_type(); |
4815 | 1767 } |
0 | 1768 } |
1769 | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2417
diff
changeset
|
1770 if (is_instance) { |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1771 // If we have an instance type and our memory input is the |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1772 // programs's initial memory state, there is no matching store, |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1773 // so just return a zero of the appropriate type |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1774 Node *mem = in(MemNode::Memory); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1775 if (mem->is_Parm() && mem->in(0)->is_Start()) { |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1776 assert(mem->as_Parm()->_con == TypeFunc::Memory, "must be memory Parm"); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1777 return Type::get_zero_type(_type->basic_type()); |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1778 } |
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
1779 } |
0 | 1780 return _type; |
1781 } | |
1782 | |
1783 //------------------------------match_edge------------------------------------- | |
1784 // Do we Match on this edge index or not? Match only the address. | |
1785 uint LoadNode::match_edge(uint idx) const { | |
1786 return idx == MemNode::Address; | |
1787 } | |
1788 | |
1789 //--------------------------LoadBNode::Ideal-------------------------------------- | |
1790 // | |
1791 // If the previous store is to the same address as this load, | |
1792 // and the value stored was larger than a byte, replace this load | |
1793 // with the value stored truncated to a byte. If no truncation is | |
1794 // needed, the replacement is done in LoadNode::Identity(). | |
1795 // | |
1796 Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1797 Node* mem = in(MemNode::Memory); | |
1798 Node* value = can_see_stored_value(mem,phase); | |
1799 if( value && !phase->type(value)->higher_equal( _type ) ) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1800 Node *result = phase->transform( new (phase->C) LShiftINode(value, phase->intcon(24)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1801 return new (phase->C) RShiftINode(result, phase->intcon(24)); |
0 | 1802 } |
1803 // Identity call will handle the case where truncation is not needed. | |
1804 return LoadNode::Ideal(phase, can_reshape); | |
1805 } | |
1806 | |
4815 | 1807 const Type* LoadBNode::Value(PhaseTransform *phase) const { |
1808 Node* mem = in(MemNode::Memory); | |
1809 Node* value = can_see_stored_value(mem,phase); | |
4821 | 1810 if (value != NULL && value->is_Con() && |
1811 !value->bottom_type()->higher_equal(_type)) { | |
4815 | 1812 // If the input to the store does not fit with the load's result type, |
1813 // it must be truncated. We can't delay until Ideal call since | |
1814 // a singleton Value is needed for split_thru_phi optimization. | |
1815 int con = value->get_int(); | |
1816 return TypeInt::make((con << 24) >> 24); | |
1817 } | |
1818 return LoadNode::Value(phase); | |
1819 } | |
1820 | |
624 | 1821 //--------------------------LoadUBNode::Ideal------------------------------------- |
1822 // | |
1823 // If the previous store is to the same address as this load, | |
1824 // and the value stored was larger than a byte, replace this load | |
1825 // with the value stored truncated to a byte. If no truncation is | |
1826 // needed, the replacement is done in LoadNode::Identity(). | |
1827 // | |
1828 Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
1829 Node* mem = in(MemNode::Memory); | |
1830 Node* value = can_see_stored_value(mem, phase); | |
1831 if (value && !phase->type(value)->higher_equal(_type)) | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1832 return new (phase->C) AndINode(value, phase->intcon(0xFF)); |
624 | 1833 // Identity call will handle the case where truncation is not needed. |
1834 return LoadNode::Ideal(phase, can_reshape); | |
1835 } | |
1836 | |
4815 | 1837 const Type* LoadUBNode::Value(PhaseTransform *phase) const { |
1838 Node* mem = in(MemNode::Memory); | |
1839 Node* value = can_see_stored_value(mem,phase); | |
4821 | 1840 if (value != NULL && value->is_Con() && |
1841 !value->bottom_type()->higher_equal(_type)) { | |
4815 | 1842 // If the input to the store does not fit with the load's result type, |
1843 // it must be truncated. We can't delay until Ideal call since | |
1844 // a singleton Value is needed for split_thru_phi optimization. | |
1845 int con = value->get_int(); | |
1846 return TypeInt::make(con & 0xFF); | |
1847 } | |
1848 return LoadNode::Value(phase); | |
1849 } | |
1850 | |
558
3b5ac9e7e6ea
6796746: rename LoadC (char) opcode class to LoadUS (unsigned short)
twisti
parents:
553
diff
changeset
|
1851 //--------------------------LoadUSNode::Ideal------------------------------------- |
0 | 1852 // |
1853 // If the previous store is to the same address as this load, | |
1854 // and the value stored was larger than a char, replace this load | |
1855 // with the value stored truncated to a char. If no truncation is | |
1856 // needed, the replacement is done in LoadNode::Identity(). | |
1857 // | |
558
3b5ac9e7e6ea
6796746: rename LoadC (char) opcode class to LoadUS (unsigned short)
twisti
parents:
553
diff
changeset
|
1858 Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
0 | 1859 Node* mem = in(MemNode::Memory); |
1860 Node* value = can_see_stored_value(mem,phase); | |
1861 if( value && !phase->type(value)->higher_equal( _type ) ) | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1862 return new (phase->C) AndINode(value,phase->intcon(0xFFFF)); |
0 | 1863 // Identity call will handle the case where truncation is not needed. |
1864 return LoadNode::Ideal(phase, can_reshape); | |
1865 } | |
1866 | |
4815 | 1867 const Type* LoadUSNode::Value(PhaseTransform *phase) const { |
1868 Node* mem = in(MemNode::Memory); | |
1869 Node* value = can_see_stored_value(mem,phase); | |
4821 | 1870 if (value != NULL && value->is_Con() && |
1871 !value->bottom_type()->higher_equal(_type)) { | |
4815 | 1872 // If the input to the store does not fit with the load's result type, |
1873 // it must be truncated. We can't delay until Ideal call since | |
1874 // a singleton Value is needed for split_thru_phi optimization. | |
1875 int con = value->get_int(); | |
1876 return TypeInt::make(con & 0xFFFF); | |
1877 } | |
1878 return LoadNode::Value(phase); | |
1879 } | |
1880 | |
0 | 1881 //--------------------------LoadSNode::Ideal-------------------------------------- |
1882 // | |
1883 // If the previous store is to the same address as this load, | |
1884 // and the value stored was larger than a short, replace this load | |
1885 // with the value stored truncated to a short. If no truncation is | |
1886 // needed, the replacement is done in LoadNode::Identity(). | |
1887 // | |
1888 Node *LoadSNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1889 Node* mem = in(MemNode::Memory); | |
1890 Node* value = can_see_stored_value(mem,phase); | |
1891 if( value && !phase->type(value)->higher_equal( _type ) ) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1892 Node *result = phase->transform( new (phase->C) LShiftINode(value, phase->intcon(16)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1893 return new (phase->C) RShiftINode(result, phase->intcon(16)); |
0 | 1894 } |
1895 // Identity call will handle the case where truncation is not needed. | |
1896 return LoadNode::Ideal(phase, can_reshape); | |
1897 } | |
1898 | |
4815 | 1899 const Type* LoadSNode::Value(PhaseTransform *phase) const { |
1900 Node* mem = in(MemNode::Memory); | |
1901 Node* value = can_see_stored_value(mem,phase); | |
4821 | 1902 if (value != NULL && value->is_Con() && |
1903 !value->bottom_type()->higher_equal(_type)) { | |
4815 | 1904 // If the input to the store does not fit with the load's result type, |
1905 // it must be truncated. We can't delay until Ideal call since | |
1906 // a singleton Value is needed for split_thru_phi optimization. | |
1907 int con = value->get_int(); | |
1908 return TypeInt::make((con << 16) >> 16); | |
1909 } | |
1910 return LoadNode::Value(phase); | |
1911 } | |
1912 | |
0 | 1913 //============================================================================= |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1914 //----------------------------LoadKlassNode::make------------------------------ |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1915 // Polymorphic factory method: |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1916 Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk ) { |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1917 Compile* C = gvn.C; |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1918 Node *ctl = NULL; |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1919 // sanity check the alias category against the created node type |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1920 const TypePtr *adr_type = adr->bottom_type()->isa_ptr(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1921 assert(adr_type != NULL, "expecting TypeKlassPtr"); |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1922 #ifdef _LP64 |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
1923 if (adr_type->is_ptr_to_narrowklass()) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
1924 assert(UseCompressedKlassPointers, "no compressed klasses"); |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
1925 Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass())); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
1926 return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr()); |
168
7793bd37a336
6705887: Compressed Oops: generate x64 addressing and implicit null checks with narrow oops
kvn
parents:
164
diff
changeset
|
1927 } |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1928 #endif |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
1929 assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop"); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1930 return new (C) LoadKlassNode(ctl, mem, adr, at, tk); |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1931 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1932 |
0 | 1933 //------------------------------Value------------------------------------------ |
1934 const Type *LoadKlassNode::Value( PhaseTransform *phase ) const { | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1935 return klass_value_common(phase); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1936 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1937 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
1938 const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const { |
0 | 1939 // Either input is TOP ==> the result is TOP |
1940 const Type *t1 = phase->type( in(MemNode::Memory) ); | |
1941 if (t1 == Type::TOP) return Type::TOP; | |
1942 Node *adr = in(MemNode::Address); | |
1943 const Type *t2 = phase->type( adr ); | |
1944 if (t2 == Type::TOP) return Type::TOP; | |
1945 const TypePtr *tp = t2->is_ptr(); | |
1946 if (TypePtr::above_centerline(tp->ptr()) || | |
1947 tp->ptr() == TypePtr::Null) return Type::TOP; | |
1948 | |
1949 // Return a more precise klass, if possible | |
1950 const TypeInstPtr *tinst = tp->isa_instptr(); | |
1951 if (tinst != NULL) { | |
1952 ciInstanceKlass* ik = tinst->klass()->as_instance_klass(); | |
1953 int offset = tinst->offset(); | |
1954 if (ik == phase->C->env()->Class_klass() | |
1955 && (offset == java_lang_Class::klass_offset_in_bytes() || | |
1956 offset == java_lang_Class::array_klass_offset_in_bytes())) { | |
1957 // We are loading a special hidden field from a Class mirror object, | |
1958 // the field which points to the VM's Klass metaobject. | |
1959 ciType* t = tinst->java_mirror_type(); | |
1960 // java_mirror_type returns non-null for compile-time Class constants. | |
1961 if (t != NULL) { | |
1962 // constant oop => constant klass | |
1963 if (offset == java_lang_Class::array_klass_offset_in_bytes()) { | |
1964 return TypeKlassPtr::make(ciArrayKlass::make(t)); | |
1965 } | |
1966 if (!t->is_klass()) { | |
1967 // a primitive Class (e.g., int.class) has NULL for a klass field | |
1968 return TypePtr::NULL_PTR; | |
1969 } | |
1970 // (Folds up the 1st indirection in aClassConstant.getModifiers().) | |
1971 return TypeKlassPtr::make(t->as_klass()); | |
1972 } | |
1973 // non-constant mirror, so we can't tell what's going on | |
1974 } | |
1975 if( !ik->is_loaded() ) | |
1976 return _type; // Bail out if not loaded | |
1977 if (offset == oopDesc::klass_offset_in_bytes()) { | |
1978 if (tinst->klass_is_exact()) { | |
1979 return TypeKlassPtr::make(ik); | |
1980 } | |
1981 // See if we can become precise: no subklasses and no interface | |
1982 // (Note: We need to support verified interfaces.) | |
1983 if (!ik->is_interface() && !ik->has_subklass()) { | |
1984 //assert(!UseExactTypes, "this code should be useless with exact types"); | |
1985 // Add a dependence; if any subclass added we need to recompile | |
1986 if (!ik->is_final()) { | |
1987 // %%% should use stronger assert_unique_concrete_subtype instead | |
1988 phase->C->dependencies()->assert_leaf_type(ik); | |
1989 } | |
1990 // Return precise klass | |
1991 return TypeKlassPtr::make(ik); | |
1992 } | |
1993 | |
1994 // Return root of possible klass | |
1995 return TypeKlassPtr::make(TypePtr::NotNull, ik, 0/*offset*/); | |
1996 } | |
1997 } | |
1998 | |
1999 // Check for loading klass from an array | |
2000 const TypeAryPtr *tary = tp->isa_aryptr(); | |
2001 if( tary != NULL ) { | |
2002 ciKlass *tary_klass = tary->klass(); | |
2003 if (tary_klass != NULL // can be NULL when at BOTTOM or TOP | |
2004 && tary->offset() == oopDesc::klass_offset_in_bytes()) { | |
2005 if (tary->klass_is_exact()) { | |
2006 return TypeKlassPtr::make(tary_klass); | |
2007 } | |
2008 ciArrayKlass *ak = tary->klass()->as_array_klass(); | |
2009 // If the klass is an object array, we defer the question to the | |
2010 // array component klass. | |
2011 if( ak->is_obj_array_klass() ) { | |
2012 assert( ak->is_loaded(), "" ); | |
2013 ciKlass *base_k = ak->as_obj_array_klass()->base_element_klass(); | |
2014 if( base_k->is_loaded() && base_k->is_instance_klass() ) { | |
2015 ciInstanceKlass* ik = base_k->as_instance_klass(); | |
2016 // See if we can become precise: no subklasses and no interface | |
2017 if (!ik->is_interface() && !ik->has_subklass()) { | |
2018 //assert(!UseExactTypes, "this code should be useless with exact types"); | |
2019 // Add a dependence; if any subclass added we need to recompile | |
2020 if (!ik->is_final()) { | |
2021 phase->C->dependencies()->assert_leaf_type(ik); | |
2022 } | |
2023 // Return precise array klass | |
2024 return TypeKlassPtr::make(ak); | |
2025 } | |
2026 } | |
2027 return TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/); | |
2028 } else { // Found a type-array? | |
2029 //assert(!UseExactTypes, "this code should be useless with exact types"); | |
2030 assert( ak->is_type_array_klass(), "" ); | |
2031 return TypeKlassPtr::make(ak); // These are always precise | |
2032 } | |
2033 } | |
2034 } | |
2035 | |
2036 // Check for loading klass from an array klass | |
2037 const TypeKlassPtr *tkls = tp->isa_klassptr(); | |
2038 if (tkls != NULL && !StressReflectiveCode) { | |
2039 ciKlass* klass = tkls->klass(); | |
2040 if( !klass->is_loaded() ) | |
2041 return _type; // Bail out if not loaded | |
2042 if( klass->is_obj_array_klass() && | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
2043 tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) { |
0 | 2044 ciKlass* elem = klass->as_obj_array_klass()->element_klass(); |
2045 // // Always returning precise element type is incorrect, | |
2046 // // e.g., element type could be object and array may contain strings | |
2047 // return TypeKlassPtr::make(TypePtr::Constant, elem, 0); | |
2048 | |
2049 // The array's TypeKlassPtr was declared 'precise' or 'not precise' | |
2050 // according to the element type's subclassing. | |
2051 return TypeKlassPtr::make(tkls->ptr(), elem, 0/*offset*/); | |
2052 } | |
2053 if( klass->is_instance_klass() && tkls->klass_is_exact() && | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
2054 tkls->offset() == in_bytes(Klass::super_offset())) { |
0 | 2055 ciKlass* sup = klass->as_instance_klass()->super(); |
2056 // The field is Klass::_super. Return its (constant) value. | |
2057 // (Folds up the 2nd indirection in aClassConstant.getSuperClass().) | |
2058 return sup ? TypeKlassPtr::make(sup) : TypePtr::NULL_PTR; | |
2059 } | |
2060 } | |
2061 | |
2062 // Bailout case | |
2063 return LoadNode::Value(phase); | |
2064 } | |
2065 | |
2066 //------------------------------Identity--------------------------------------- | |
2067 // To clean up reflective code, simplify k.java_mirror.as_klass to plain k. | |
2068 // Also feed through the klass in Allocate(...klass...)._klass. | |
2069 Node* LoadKlassNode::Identity( PhaseTransform *phase ) { | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2070 return klass_identity_common(phase); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2071 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2072 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2073 Node* LoadNode::klass_identity_common(PhaseTransform *phase ) { |
0 | 2074 Node* x = LoadNode::Identity(phase); |
2075 if (x != this) return x; | |
2076 | |
2077 // Take apart the address into an oop and and offset. | |
2078 // Return 'this' if we cannot. | |
2079 Node* adr = in(MemNode::Address); | |
2080 intptr_t offset = 0; | |
2081 Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); | |
2082 if (base == NULL) return this; | |
2083 const TypeOopPtr* toop = phase->type(adr)->isa_oopptr(); | |
2084 if (toop == NULL) return this; | |
2085 | |
2086 // We can fetch the klass directly through an AllocateNode. | |
2087 // This works even if the klass is not constant (clone or newArray). | |
2088 if (offset == oopDesc::klass_offset_in_bytes()) { | |
2089 Node* allocated_klass = AllocateNode::Ideal_klass(base, phase); | |
2090 if (allocated_klass != NULL) { | |
2091 return allocated_klass; | |
2092 } | |
2093 } | |
2094 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
2095 // Simplify k.java_mirror.as_klass to plain k, where k is a Klass*. |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
2096 // Simplify ak.component_mirror.array_klass to plain ak, ak an ArrayKlass. |
0 | 2097 // See inline_native_Class_query for occurrences of these patterns. |
2098 // Java Example: x.getClass().isAssignableFrom(y) | |
2099 // Java Example: Array.newInstance(x.getClass().getComponentType(), n) | |
2100 // | |
2101 // This improves reflective code, often making the Class | |
2102 // mirror go completely dead. (Current exception: Class | |
2103 // mirrors may appear in debug info, but we could clean them out by | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
2104 // introducing a new debug info operator for Klass*.java_mirror). |
0 | 2105 if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass() |
2106 && (offset == java_lang_Class::klass_offset_in_bytes() || | |
2107 offset == java_lang_Class::array_klass_offset_in_bytes())) { | |
2108 // We are loading a special hidden field from a Class mirror, | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
2109 // the field which points to its Klass or ArrayKlass metaobject. |
0 | 2110 if (base->is_Load()) { |
2111 Node* adr2 = base->in(MemNode::Address); | |
2112 const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr(); | |
2113 if (tkls != NULL && !tkls->empty() | |
2114 && (tkls->klass()->is_instance_klass() || | |
2115 tkls->klass()->is_array_klass()) | |
2116 && adr2->is_AddP() | |
2117 ) { | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
2118 int mirror_field = in_bytes(Klass::java_mirror_offset()); |
0 | 2119 if (offset == java_lang_Class::array_klass_offset_in_bytes()) { |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
2120 mirror_field = in_bytes(ArrayKlass::component_mirror_offset()); |
0 | 2121 } |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
4124
diff
changeset
|
2122 if (tkls->offset() == mirror_field) { |
0 | 2123 return adr2->in(AddPNode::Base); |
2124 } | |
2125 } | |
2126 } | |
2127 } | |
2128 | |
2129 return this; | |
2130 } | |
2131 | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2132 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2133 //------------------------------Value------------------------------------------ |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2134 const Type *LoadNKlassNode::Value( PhaseTransform *phase ) const { |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2135 const Type *t = klass_value_common(phase); |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
193
diff
changeset
|
2136 if (t == Type::TOP) |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
193
diff
changeset
|
2137 return t; |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
193
diff
changeset
|
2138 |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2139 return t->make_narrowklass(); |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2140 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2141 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2142 //------------------------------Identity--------------------------------------- |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2143 // To clean up reflective code, simplify k.java_mirror.as_klass to narrow k. |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2144 // Also feed through the klass in Allocate(...klass...)._klass. |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2145 Node* LoadNKlassNode::Identity( PhaseTransform *phase ) { |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2146 Node *x = klass_identity_common(phase); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2147 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2148 const Type *t = phase->type( x ); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2149 if( t == Type::TOP ) return x; |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2150 if( t->isa_narrowklass()) return x; |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2151 assert (!t->isa_narrowoop(), "no narrow oop here"); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2152 |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2153 return phase->transform(new (phase->C) EncodePKlassNode(x, t->make_narrowklass())); |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2154 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2155 |
0 | 2156 //------------------------------Value----------------------------------------- |
2157 const Type *LoadRangeNode::Value( PhaseTransform *phase ) const { | |
2158 // Either input is TOP ==> the result is TOP | |
2159 const Type *t1 = phase->type( in(MemNode::Memory) ); | |
2160 if( t1 == Type::TOP ) return Type::TOP; | |
2161 Node *adr = in(MemNode::Address); | |
2162 const Type *t2 = phase->type( adr ); | |
2163 if( t2 == Type::TOP ) return Type::TOP; | |
2164 const TypePtr *tp = t2->is_ptr(); | |
2165 if (TypePtr::above_centerline(tp->ptr())) return Type::TOP; | |
2166 const TypeAryPtr *tap = tp->isa_aryptr(); | |
2167 if( !tap ) return _type; | |
2168 return tap->size(); | |
2169 } | |
2170 | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2171 //-------------------------------Ideal--------------------------------------- |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2172 // Feed through the length in AllocateArray(...length...)._length. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2173 Node *LoadRangeNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2174 Node* p = MemNode::Ideal_common(phase, can_reshape); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2175 if (p) return (p == NodeSentinel) ? NULL : p; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2176 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2177 // Take apart the address into an oop and and offset. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2178 // Return 'this' if we cannot. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2179 Node* adr = in(MemNode::Address); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2180 intptr_t offset = 0; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2181 Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2182 if (base == NULL) return NULL; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2183 const TypeAryPtr* tary = phase->type(adr)->isa_aryptr(); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2184 if (tary == NULL) return NULL; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2185 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2186 // We can fetch the length directly through an AllocateArrayNode. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2187 // This works even if the length is not constant (clone or newArray). |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2188 if (offset == arrayOopDesc::length_offset_in_bytes()) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2189 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(base, phase); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2190 if (alloc != NULL) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2191 Node* allocated_length = alloc->Ideal_length(); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2192 Node* len = alloc->make_ideal_length(tary, phase); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2193 if (allocated_length != len) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2194 // New CastII improves on this. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2195 return len; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2196 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2197 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2198 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2199 |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2200 return NULL; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2201 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2202 |
0 | 2203 //------------------------------Identity--------------------------------------- |
2204 // Feed through the length in AllocateArray(...length...)._length. | |
2205 Node* LoadRangeNode::Identity( PhaseTransform *phase ) { | |
2206 Node* x = LoadINode::Identity(phase); | |
2207 if (x != this) return x; | |
2208 | |
2209 // Take apart the address into an oop and and offset. | |
2210 // Return 'this' if we cannot. | |
2211 Node* adr = in(MemNode::Address); | |
2212 intptr_t offset = 0; | |
2213 Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); | |
2214 if (base == NULL) return this; | |
2215 const TypeAryPtr* tary = phase->type(adr)->isa_aryptr(); | |
2216 if (tary == NULL) return this; | |
2217 | |
2218 // We can fetch the length directly through an AllocateArrayNode. | |
2219 // This works even if the length is not constant (clone or newArray). | |
2220 if (offset == arrayOopDesc::length_offset_in_bytes()) { | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2221 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(base, phase); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2222 if (alloc != NULL) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2223 Node* allocated_length = alloc->Ideal_length(); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2224 // Do not allow make_ideal_length to allocate a CastII node. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2225 Node* len = alloc->make_ideal_length(tary, phase, false); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2226 if (allocated_length == len) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2227 // Return allocated_length only if it would not be improved by a CastII. |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2228 return allocated_length; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2229 } |
0 | 2230 } |
2231 } | |
2232 | |
2233 return this; | |
2234 | |
2235 } | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
305
diff
changeset
|
2236 |
0 | 2237 //============================================================================= |
2238 //---------------------------StoreNode::make----------------------------------- | |
2239 // Polymorphic factory method: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2240 StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2241 Compile* C = gvn.C; |
1609 | 2242 assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw || |
2243 ctl != NULL, "raw memory operations should have control edge"); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2244 |
0 | 2245 switch (bt) { |
2246 case T_BOOLEAN: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2247 case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2248 case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val); |
0 | 2249 case T_CHAR: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2250 case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2251 case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2252 case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2253 case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6179
diff
changeset
|
2254 case T_METADATA: |
0 | 2255 case T_ADDRESS: |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2256 case T_OBJECT: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2257 #ifdef _LP64 |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2258 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2259 val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop())); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2260 return new (C) StoreNNode(ctl, mem, adr, adr_type, val); |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2261 } else if (adr->bottom_type()->is_ptr_to_narrowklass() || |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2262 (UseCompressedKlassPointers && val->bottom_type()->isa_klassptr() && |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2263 adr->bottom_type()->isa_rawptr())) { |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2264 val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass())); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2265 return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6804
diff
changeset
|
2266 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2267 #endif |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
193
diff
changeset
|
2268 { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2269 return new (C) StorePNode(ctl, mem, adr, adr_type, val); |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
193
diff
changeset
|
2270 } |
0 | 2271 } |
2272 ShouldNotReachHere(); | |
2273 return (StoreNode*)NULL; | |
2274 } | |
2275 | |
2276 StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val) { | |
2277 bool require_atomic = true; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2278 return new (C) StoreLNode(ctl, mem, adr, adr_type, val, require_atomic); |
0 | 2279 } |
2280 | |
2281 | |
2282 //--------------------------bottom_type---------------------------------------- | |
2283 const Type *StoreNode::bottom_type() const { | |
2284 return Type::MEMORY; | |
2285 } | |
2286 | |
2287 //------------------------------hash------------------------------------------- | |
2288 uint StoreNode::hash() const { | |
2289 // unroll addition of interesting fields | |
2290 //return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address) + (uintptr_t)in(ValueIn); | |
2291 | |
2292 // Since they are not commoned, do not hash them: | |
2293 return NO_HASH; | |
2294 } | |
2295 | |
2296 //------------------------------Ideal------------------------------------------ | |
2297 // Change back-to-back Store(, p, x) -> Store(m, p, y) to Store(m, p, x). | |
2298 // When a store immediately follows a relevant allocation/initialization, | |
2299 // try to capture it into the initialization, or hoist it above. | |
2300 Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
2301 Node* p = MemNode::Ideal_common(phase, can_reshape); | |
2302 if (p) return (p == NodeSentinel) ? NULL : p; | |
2303 | |
2304 Node* mem = in(MemNode::Memory); | |
2305 Node* address = in(MemNode::Address); | |
2306 | |
3248
e6beb62de02d
7032963: StoreCM shouldn't participate in store elimination
never
parents:
2379
diff
changeset
|
2307 // Back-to-back stores to same address? Fold em up. Generally |
e6beb62de02d
7032963: StoreCM shouldn't participate in store elimination
never
parents:
2379
diff
changeset
|
2308 // unsafe if I have intervening uses... Also disallowed for StoreCM |
e6beb62de02d
7032963: StoreCM shouldn't participate in store elimination
never
parents:
2379
diff
changeset
|
2309 // since they must follow each StoreP operation. Redundant StoreCMs |
e6beb62de02d
7032963: StoreCM shouldn't participate in store elimination
never
parents:
2379
diff
changeset
|
2310 // are eliminated just before matching in final_graph_reshape. |
4778 | 2311 if (mem->is_Store() && mem->in(MemNode::Address)->eqv_uncast(address) && |
3248
e6beb62de02d
7032963: StoreCM shouldn't participate in store elimination
never
parents:
2379
diff
changeset
|
2312 mem->Opcode() != Op_StoreCM) { |
0 | 2313 // Looking at a dead closed cycle of memory? |
2314 assert(mem != mem->in(MemNode::Memory), "dead loop in StoreNode::Ideal"); | |
2315 | |
2316 assert(Opcode() == mem->Opcode() || | |
2317 phase->C->get_alias_index(adr_type()) == Compile::AliasIdxRaw, | |
2318 "no mismatched stores, except on raw memory"); | |
2319 | |
2320 if (mem->outcnt() == 1 && // check for intervening uses | |
2321 mem->as_Store()->memory_size() <= this->memory_size()) { | |
2322 // If anybody other than 'this' uses 'mem', we cannot fold 'mem' away. | |
2323 // For example, 'mem' might be the final state at a conditional return. | |
2324 // Or, 'mem' might be used by some node which is live at the same time | |
2325 // 'this' is live, which might be unschedulable. So, require exactly | |
2326 // ONE user, the 'this' store, until such time as we clone 'mem' for | |
2327 // each of 'mem's uses (thus making the exactly-1-user-rule hold true). | |
2328 if (can_reshape) { // (%%% is this an anachronism?) | |
2329 set_req_X(MemNode::Memory, mem->in(MemNode::Memory), | |
2330 phase->is_IterGVN()); | |
2331 } else { | |
2332 // It's OK to do this in the parser, since DU info is always accurate, | |
2333 // and the parser always refers to nodes via SafePointNode maps. | |
2334 set_req(MemNode::Memory, mem->in(MemNode::Memory)); | |
2335 } | |
2336 return this; | |
2337 } | |
2338 } | |
2339 | |
2340 // Capture an unaliased, unconditional, simple store into an initializer. | |
2341 // Or, if it is independent of the allocation, hoist it above the allocation. | |
2342 if (ReduceFieldZeroing && /*can_reshape &&*/ | |
2343 mem->is_Proj() && mem->in(0)->is_Initialize()) { | |
2344 InitializeNode* init = mem->in(0)->as_Initialize(); | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
2345 intptr_t offset = init->can_capture_store(this, phase, can_reshape); |
0 | 2346 if (offset > 0) { |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
2347 Node* moved = init->capture_store(this, offset, phase, can_reshape); |
0 | 2348 // If the InitializeNode captured me, it made a raw copy of me, |
2349 // and I need to disappear. | |
2350 if (moved != NULL) { | |
2351 // %%% hack to ensure that Ideal returns a new node: | |
2352 mem = MergeMemNode::make(phase->C, mem); | |
2353 return mem; // fold me away | |
2354 } | |
2355 } | |
2356 } | |
2357 | |
2358 return NULL; // No further progress | |
2359 } | |
2360 | |
2361 //------------------------------Value----------------------------------------- | |
2362 const Type *StoreNode::Value( PhaseTransform *phase ) const { | |
2363 // Either input is TOP ==> the result is TOP | |
2364 const Type *t1 = phase->type( in(MemNode::Memory) ); | |
2365 if( t1 == Type::TOP ) return Type::TOP; | |
2366 const Type *t2 = phase->type( in(MemNode::Address) ); | |
2367 if( t2 == Type::TOP ) return Type::TOP; | |
2368 const Type *t3 = phase->type( in(MemNode::ValueIn) ); | |
2369 if( t3 == Type::TOP ) return Type::TOP; | |
2370 return Type::MEMORY; | |
2371 } | |
2372 | |
2373 //------------------------------Identity--------------------------------------- | |
2374 // Remove redundant stores: | |
2375 // Store(m, p, Load(m, p)) changes to m. | |
2376 // Store(, p, x) -> Store(m, p, x) changes to Store(m, p, x). | |
2377 Node *StoreNode::Identity( PhaseTransform *phase ) { | |
2378 Node* mem = in(MemNode::Memory); | |
2379 Node* adr = in(MemNode::Address); | |
2380 Node* val = in(MemNode::ValueIn); | |
2381 | |
2382 // Load then Store? Then the Store is useless | |
2383 if (val->is_Load() && | |
4778 | 2384 val->in(MemNode::Address)->eqv_uncast(adr) && |
2385 val->in(MemNode::Memory )->eqv_uncast(mem) && | |
0 | 2386 val->as_Load()->store_Opcode() == Opcode()) { |
2387 return mem; | |
2388 } | |
2389 | |
2390 // Two stores in a row of the same value? | |
2391 if (mem->is_Store() && | |
4778 | 2392 mem->in(MemNode::Address)->eqv_uncast(adr) && |
2393 mem->in(MemNode::ValueIn)->eqv_uncast(val) && | |
0 | 2394 mem->Opcode() == Opcode()) { |
2395 return mem; | |
2396 } | |
2397 | |
2398 // Store of zero anywhere into a freshly-allocated object? | |
2399 // Then the store is useless. | |
2400 // (It must already have been captured by the InitializeNode.) | |
2401 if (ReduceFieldZeroing && phase->type(val)->is_zero_type()) { | |
2402 // a newly allocated object is already all-zeroes everywhere | |
2403 if (mem->is_Proj() && mem->in(0)->is_Allocate()) { | |
2404 return mem; | |
2405 } | |
2406 | |
2407 // the store may also apply to zero-bits in an earlier object | |
2408 Node* prev_mem = find_previous_store(phase); | |
2409 // Steps (a), (b): Walk past independent stores to find an exact match. | |
2410 if (prev_mem != NULL) { | |
2411 Node* prev_val = can_see_stored_value(prev_mem, phase); | |
2412 if (prev_val != NULL && phase->eqv(prev_val, val)) { | |
2413 // prev_val and val might differ by a cast; it would be good | |
2414 // to keep the more informative of the two. | |
2415 return mem; | |
2416 } | |
2417 } | |
2418 } | |
2419 | |
2420 return this; | |
2421 } | |
2422 | |
2423 //------------------------------match_edge------------------------------------- | |
2424 // Do we Match on this edge index or not? Match only memory & value | |
2425 uint StoreNode::match_edge(uint idx) const { | |
2426 return idx == MemNode::Address || idx == MemNode::ValueIn; | |
2427 } | |
2428 | |
2429 //------------------------------cmp-------------------------------------------- | |
2430 // Do not common stores up together. They generally have to be split | |
2431 // back up anyways, so do not bother. | |
2432 uint StoreNode::cmp( const Node &n ) const { | |
2433 return (&n == this); // Always fail except on self | |
2434 } | |
2435 | |
2436 //------------------------------Ideal_masked_input----------------------------- | |
2437 // Check for a useless mask before a partial-word store | |
2438 // (StoreB ... (AndI valIn conIa) ) | |
2439 // If (conIa & mask == mask) this simplifies to | |
2440 // (StoreB ... (valIn) ) | |
2441 Node *StoreNode::Ideal_masked_input(PhaseGVN *phase, uint mask) { | |
2442 Node *val = in(MemNode::ValueIn); | |
2443 if( val->Opcode() == Op_AndI ) { | |
2444 const TypeInt *t = phase->type( val->in(2) )->isa_int(); | |
2445 if( t && t->is_con() && (t->get_con() & mask) == mask ) { | |
2446 set_req(MemNode::ValueIn, val->in(1)); | |
2447 return this; | |
2448 } | |
2449 } | |
2450 return NULL; | |
2451 } | |
2452 | |
2453 | |
2454 //------------------------------Ideal_sign_extended_input---------------------- | |
2455 // Check for useless sign-extension before a partial-word store | |
2456 // (StoreB ... (RShiftI _ (LShiftI _ valIn conIL ) conIR) ) | |
2457 // If (conIL == conIR && conIR <= num_bits) this simplifies to | |
2458 // (StoreB ... (valIn) ) | |
2459 Node *StoreNode::Ideal_sign_extended_input(PhaseGVN *phase, int num_bits) { | |
2460 Node *val = in(MemNode::ValueIn); | |
2461 if( val->Opcode() == Op_RShiftI ) { | |
2462 const TypeInt *t = phase->type( val->in(2) )->isa_int(); | |
2463 if( t && t->is_con() && (t->get_con() <= num_bits) ) { | |
2464 Node *shl = val->in(1); | |
2465 if( shl->Opcode() == Op_LShiftI ) { | |
2466 const TypeInt *t2 = phase->type( shl->in(2) )->isa_int(); | |
2467 if( t2 && t2->is_con() && (t2->get_con() == t->get_con()) ) { | |
2468 set_req(MemNode::ValueIn, shl->in(1)); | |
2469 return this; | |
2470 } | |
2471 } | |
2472 } | |
2473 } | |
2474 return NULL; | |
2475 } | |
2476 | |
2477 //------------------------------value_never_loaded----------------------------------- | |
2478 // Determine whether there are any possible loads of the value stored. | |
2479 // For simplicity, we actually check if there are any loads from the | |
2480 // address stored to, not just for loads of the value stored by this node. | |
2481 // | |
2482 bool StoreNode::value_never_loaded( PhaseTransform *phase) const { | |
2483 Node *adr = in(Address); | |
2484 const TypeOopPtr *adr_oop = phase->type(adr)->isa_oopptr(); | |
2485 if (adr_oop == NULL) | |
2486 return false; | |
223 | 2487 if (!adr_oop->is_known_instance_field()) |
0 | 2488 return false; // if not a distinct instance, there may be aliases of the address |
2489 for (DUIterator_Fast imax, i = adr->fast_outs(imax); i < imax; i++) { | |
2490 Node *use = adr->fast_out(i); | |
2491 int opc = use->Opcode(); | |
2492 if (use->is_Load() || use->is_LoadStore()) { | |
2493 return false; | |
2494 } | |
2495 } | |
2496 return true; | |
2497 } | |
2498 | |
2499 //============================================================================= | |
2500 //------------------------------Ideal------------------------------------------ | |
2501 // If the store is from an AND mask that leaves the low bits untouched, then | |
2502 // we can skip the AND operation. If the store is from a sign-extension | |
2503 // (a left shift, then right shift) we can skip both. | |
2504 Node *StoreBNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
2505 Node *progress = StoreNode::Ideal_masked_input(phase, 0xFF); | |
2506 if( progress != NULL ) return progress; | |
2507 | |
2508 progress = StoreNode::Ideal_sign_extended_input(phase, 24); | |
2509 if( progress != NULL ) return progress; | |
2510 | |
2511 // Finally check the default case | |
2512 return StoreNode::Ideal(phase, can_reshape); | |
2513 } | |
2514 | |
2515 //============================================================================= | |
2516 //------------------------------Ideal------------------------------------------ | |
2517 // If the store is from an AND mask that leaves the low bits untouched, then | |
2518 // we can skip the AND operation | |
2519 Node *StoreCNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
2520 Node *progress = StoreNode::Ideal_masked_input(phase, 0xFFFF); | |
2521 if( progress != NULL ) return progress; | |
2522 | |
2523 progress = StoreNode::Ideal_sign_extended_input(phase, 16); | |
2524 if( progress != NULL ) return progress; | |
2525 | |
2526 // Finally check the default case | |
2527 return StoreNode::Ideal(phase, can_reshape); | |
2528 } | |
2529 | |
2530 //============================================================================= | |
2531 //------------------------------Identity--------------------------------------- | |
2532 Node *StoreCMNode::Identity( PhaseTransform *phase ) { | |
2533 // No need to card mark when storing a null ptr | |
2534 Node* my_store = in(MemNode::OopStore); | |
2535 if (my_store->is_Store()) { | |
2536 const Type *t1 = phase->type( my_store->in(MemNode::ValueIn) ); | |
2537 if( t1 == TypePtr::NULL_PTR ) { | |
2538 return in(MemNode::Memory); | |
2539 } | |
2540 } | |
2541 return this; | |
2542 } | |
2543 | |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2544 //============================================================================= |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2545 //------------------------------Ideal--------------------------------------- |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2546 Node *StoreCMNode::Ideal(PhaseGVN *phase, bool can_reshape){ |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2547 Node* progress = StoreNode::Ideal(phase, can_reshape); |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2548 if (progress != NULL) return progress; |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2549 |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2550 Node* my_store = in(MemNode::OopStore); |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2551 if (my_store->is_MergeMem()) { |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2552 Node* mem = my_store->as_MergeMem()->memory_at(oop_alias_idx()); |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2553 set_req(MemNode::OopStore, mem); |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2554 return this; |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2555 } |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2556 |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2557 return NULL; |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2558 } |
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
708
diff
changeset
|
2559 |
0 | 2560 //------------------------------Value----------------------------------------- |
2561 const Type *StoreCMNode::Value( PhaseTransform *phase ) const { | |
43 | 2562 // Either input is TOP ==> the result is TOP |
2563 const Type *t = phase->type( in(MemNode::Memory) ); | |
2564 if( t == Type::TOP ) return Type::TOP; | |
2565 t = phase->type( in(MemNode::Address) ); | |
2566 if( t == Type::TOP ) return Type::TOP; | |
2567 t = phase->type( in(MemNode::ValueIn) ); | |
2568 if( t == Type::TOP ) return Type::TOP; | |
0 | 2569 // If extra input is TOP ==> the result is TOP |
43 | 2570 t = phase->type( in(MemNode::OopStore) ); |
2571 if( t == Type::TOP ) return Type::TOP; | |
0 | 2572 |
2573 return StoreNode::Value( phase ); | |
2574 } | |
2575 | |
2576 | |
2577 //============================================================================= | |
2578 //----------------------------------SCMemProjNode------------------------------ | |
2579 const Type * SCMemProjNode::Value( PhaseTransform *phase ) const | |
2580 { | |
2581 return bottom_type(); | |
2582 } | |
2583 | |
2584 //============================================================================= | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2585 //----------------------------------LoadStoreNode------------------------------ |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2586 LoadStoreNode::LoadStoreNode( Node *c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* rt, uint required ) |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2587 : Node(required), |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2588 _type(rt), |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2589 _adr_type(at) |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2590 { |
0 | 2591 init_req(MemNode::Control, c ); |
2592 init_req(MemNode::Memory , mem); | |
2593 init_req(MemNode::Address, adr); | |
2594 init_req(MemNode::ValueIn, val); | |
2595 init_class_id(Class_LoadStore); | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2596 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2597 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2598 uint LoadStoreNode::ideal_reg() const { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2599 return _type->ideal_reg(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2600 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2601 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2602 bool LoadStoreNode::result_not_used() const { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2603 for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2604 Node *x = fast_out(i); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2605 if (x->Opcode() == Op_SCMemProj) continue; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2606 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2607 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2608 return true; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2609 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2610 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2611 uint LoadStoreNode::size_of() const { return sizeof(*this); } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2612 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2613 //============================================================================= |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2614 //----------------------------------LoadStoreConditionalNode-------------------- |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2615 LoadStoreConditionalNode::LoadStoreConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex ) : LoadStoreNode(c, mem, adr, val, NULL, TypeInt::BOOL, 5) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2616 init_req(ExpectedIn, ex ); |
0 | 2617 } |
2618 | |
2619 //============================================================================= | |
2620 //-------------------------------adr_type-------------------------------------- | |
2621 // Do we Match on this edge index or not? Do not match memory | |
2622 const TypePtr* ClearArrayNode::adr_type() const { | |
2623 Node *adr = in(3); | |
2624 return MemNode::calculate_adr_type(adr->bottom_type()); | |
2625 } | |
2626 | |
2627 //------------------------------match_edge------------------------------------- | |
2628 // Do we Match on this edge index or not? Do not match memory | |
2629 uint ClearArrayNode::match_edge(uint idx) const { | |
2630 return idx > 1; | |
2631 } | |
2632 | |
2633 //------------------------------Identity--------------------------------------- | |
2634 // Clearing a zero length array does nothing | |
2635 Node *ClearArrayNode::Identity( PhaseTransform *phase ) { | |
68
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2636 return phase->type(in(2))->higher_equal(TypeX::ZERO) ? in(1) : this; |
0 | 2637 } |
2638 | |
2639 //------------------------------Idealize--------------------------------------- | |
2640 // Clearing a short array is faster with stores | |
2641 Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ | |
2642 const int unit = BytesPerLong; | |
2643 const TypeX* t = phase->type(in(2))->isa_intptr_t(); | |
2644 if (!t) return NULL; | |
2645 if (!t->is_con()) return NULL; | |
2646 intptr_t raw_count = t->get_con(); | |
2647 intptr_t size = raw_count; | |
2648 if (!Matcher::init_array_count_is_in_bytes) size *= unit; | |
2649 // Clearing nothing uses the Identity call. | |
2650 // Negative clears are possible on dead ClearArrays | |
2651 // (see jck test stmt114.stmt11402.val). | |
2652 if (size <= 0 || size % unit != 0) return NULL; | |
2653 intptr_t count = size / unit; | |
2654 // Length too long; use fast hardware clear | |
2655 if (size > Matcher::init_array_short_size) return NULL; | |
2656 Node *mem = in(1); | |
2657 if( phase->type(mem)==Type::TOP ) return NULL; | |
2658 Node *adr = in(3); | |
2659 const Type* at = phase->type(adr); | |
2660 if( at==Type::TOP ) return NULL; | |
2661 const TypePtr* atp = at->isa_ptr(); | |
2662 // adjust atp to be the correct array element address type | |
2663 if (atp == NULL) atp = TypePtr::BOTTOM; | |
2664 else atp = atp->add_offset(Type::OffsetBot); | |
2665 // Get base for derived pointer purposes | |
2666 if( adr->Opcode() != Op_AddP ) Unimplemented(); | |
2667 Node *base = adr->in(1); | |
2668 | |
2669 Node *zero = phase->makecon(TypeLong::ZERO); | |
2670 Node *off = phase->MakeConX(BytesPerLong); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2671 mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); |
0 | 2672 count--; |
2673 while( count-- ) { | |
2674 mem = phase->transform(mem); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2675 adr = phase->transform(new (phase->C) AddPNode(base,adr,off)); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2676 mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); |
0 | 2677 } |
2678 return mem; | |
2679 } | |
2680 | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2681 //----------------------------step_through---------------------------------- |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2682 // Return allocation input memory edge if it is different instance |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2683 // or itself if it is the one we are looking for. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2684 bool ClearArrayNode::step_through(Node** np, uint instance_id, PhaseTransform* phase) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2685 Node* n = *np; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2686 assert(n->is_ClearArray(), "sanity"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2687 intptr_t offset; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2688 AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2689 // This method is called only before Allocate nodes are expanded during |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2690 // macro nodes expansion. Before that ClearArray nodes are only generated |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2691 // in LibraryCallKit::generate_arraycopy() which follows allocations. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2692 assert(alloc != NULL, "should have allocation"); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2693 if (alloc->_idx == instance_id) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2694 // Can not bypass initialization of the instance we are looking for. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2695 return false; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2696 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2697 // Otherwise skip it. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2698 InitializeNode* init = alloc->initialization(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2699 if (init != NULL) |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2700 *np = init->in(TypeFunc::Memory); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2701 else |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2702 *np = alloc->in(TypeFunc::Memory); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2703 return true; |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2704 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2705 |
0 | 2706 //----------------------------clear_memory------------------------------------- |
2707 // Generate code to initialize object storage to zero. | |
2708 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, | |
2709 intptr_t start_offset, | |
2710 Node* end_offset, | |
2711 PhaseGVN* phase) { | |
2712 Compile* C = phase->C; | |
2713 intptr_t offset = start_offset; | |
2714 | |
2715 int unit = BytesPerLong; | |
2716 if ((offset % unit) != 0) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2717 Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(offset)); |
0 | 2718 adr = phase->transform(adr); |
2719 const TypePtr* atp = TypeRawPtr::BOTTOM; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2720 mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); |
0 | 2721 mem = phase->transform(mem); |
2722 offset += BytesPerInt; | |
2723 } | |
2724 assert((offset % unit) == 0, ""); | |
2725 | |
2726 // Initialize the remaining stuff, if any, with a ClearArray. | |
2727 return clear_memory(ctl, mem, dest, phase->MakeConX(offset), end_offset, phase); | |
2728 } | |
2729 | |
2730 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, | |
2731 Node* start_offset, | |
2732 Node* end_offset, | |
2733 PhaseGVN* phase) { | |
68
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2734 if (start_offset == end_offset) { |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2735 // nothing to do |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2736 return mem; |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2737 } |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2738 |
0 | 2739 Compile* C = phase->C; |
2740 int unit = BytesPerLong; | |
2741 Node* zbase = start_offset; | |
2742 Node* zend = end_offset; | |
2743 | |
2744 // Scale to the unit required by the CPU: | |
2745 if (!Matcher::init_array_count_is_in_bytes) { | |
2746 Node* shift = phase->intcon(exact_log2(unit)); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2747 zbase = phase->transform( new(C) URShiftXNode(zbase, shift) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2748 zend = phase->transform( new(C) URShiftXNode(zend, shift) ); |
0 | 2749 } |
2750 | |
7474
00af3a3a8df4
8005522: use fast-string instructions on x86 for zeroing
kvn
parents:
6853
diff
changeset
|
2751 // Bulk clear double-words |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2752 Node* zsize = phase->transform( new(C) SubXNode(zend, zbase) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2753 Node* adr = phase->transform( new(C) AddPNode(dest, dest, start_offset) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2754 mem = new (C) ClearArrayNode(ctl, mem, zsize, adr); |
0 | 2755 return phase->transform(mem); |
2756 } | |
2757 | |
2758 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, | |
2759 intptr_t start_offset, | |
2760 intptr_t end_offset, | |
2761 PhaseGVN* phase) { | |
68
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2762 if (start_offset == end_offset) { |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2763 // nothing to do |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2764 return mem; |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2765 } |
daf38130e60d
6676841: ClearArrayNode::Identity is incorrect for 64-bit
never
parents:
64
diff
changeset
|
2766 |
0 | 2767 Compile* C = phase->C; |
2768 assert((end_offset % BytesPerInt) == 0, "odd end offset"); | |
2769 intptr_t done_offset = end_offset; | |
2770 if ((done_offset % BytesPerLong) != 0) { | |
2771 done_offset -= BytesPerInt; | |
2772 } | |
2773 if (done_offset > start_offset) { | |
2774 mem = clear_memory(ctl, mem, dest, | |
2775 start_offset, phase->MakeConX(done_offset), phase); | |
2776 } | |
2777 if (done_offset < end_offset) { // emit the final 32-bit store | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2778 Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(done_offset)); |
0 | 2779 adr = phase->transform(adr); |
2780 const TypePtr* atp = TypeRawPtr::BOTTOM; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
2781 mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); |
0 | 2782 mem = phase->transform(mem); |
2783 done_offset += BytesPerInt; | |
2784 } | |
2785 assert(done_offset == end_offset, ""); | |
2786 return mem; | |
2787 } | |
2788 | |
2789 //============================================================================= | |
2412
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2790 // Do not match memory edge. |
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2791 uint StrIntrinsicNode::match_edge(uint idx) const { |
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2792 return idx == 2 || idx == 3; |
681 | 2793 } |
2794 | |
2795 //------------------------------Ideal------------------------------------------ | |
2796 // Return a node which is more "ideal" than the current node. Strip out | |
2797 // control copies | |
2412
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2798 Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2799 if (remove_dead_region(phase, can_reshape)) return this; |
4115 | 2800 // Don't bother trying to transform a dead node |
2801 if (in(0) && in(0)->is_top()) return NULL; | |
2412
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2802 |
2417 | 2803 if (can_reshape) { |
2804 Node* mem = phase->transform(in(MemNode::Memory)); | |
2805 // If transformed to a MergeMem, get the desired slice | |
2806 uint alias_idx = phase->C->get_alias_index(adr_type()); | |
2807 mem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(alias_idx) : mem; | |
2808 if (mem != in(MemNode::Memory)) { | |
2809 set_req(MemNode::Memory, mem); | |
2810 return this; | |
2811 } | |
2812 } | |
2412
f9424955eb18
7029152: Ideal nodes for String intrinsics miss memory edge optimization
kvn
parents:
2379
diff
changeset
|
2813 return NULL; |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
168
diff
changeset
|
2814 } |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
168
diff
changeset
|
2815 |
4115 | 2816 //------------------------------Value------------------------------------------ |
2817 const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const { | |
2818 if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; | |
2819 return bottom_type(); | |
2820 } | |
2821 | |
0 | 2822 //============================================================================= |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2823 //------------------------------match_edge------------------------------------- |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2824 // Do not match memory edge |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2825 uint EncodeISOArrayNode::match_edge(uint idx) const { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2826 return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len) |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2827 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2828 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2829 //------------------------------Ideal------------------------------------------ |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2830 // Return a node which is more "ideal" than the current node. Strip out |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2831 // control copies |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2832 Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2833 return remove_dead_region(phase, can_reshape) ? this : NULL; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2834 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2835 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2836 //------------------------------Value------------------------------------------ |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2837 const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2838 if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2839 return bottom_type(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2840 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2841 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7474
diff
changeset
|
2842 //============================================================================= |
0 | 2843 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent) |
2844 : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)), | |
2845 _adr_type(C->get_adr_type(alias_idx)) | |
2846 { | |
2847 init_class_id(Class_MemBar); | |
2848 Node* top = C->top(); | |
2849 init_req(TypeFunc::I_O,top); | |
2850 init_req(TypeFunc::FramePtr,top); | |
2851 init_req(TypeFunc::ReturnAdr,top); | |
2852 if (precedent != NULL) | |
2853 init_req(TypeFunc::Parms, precedent); | |
2854 } | |
2855 | |
2856 //------------------------------cmp-------------------------------------------- | |
2857 uint MemBarNode::hash() const { return NO_HASH; } | |
2858 uint MemBarNode::cmp( const Node &n ) const { | |
2859 return (&n == this); // Always fail except on self | |
2860 } | |
2861 | |
2862 //------------------------------make------------------------------------------- | |
2863 MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { | |
2864 switch (opcode) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2865 case Op_MemBarAcquire: return new(C) MemBarAcquireNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2866 case Op_MemBarRelease: return new(C) MemBarReleaseNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2867 case Op_MemBarAcquireLock: return new(C) MemBarAcquireLockNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2868 case Op_MemBarReleaseLock: return new(C) MemBarReleaseLockNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2869 case Op_MemBarVolatile: return new(C) MemBarVolatileNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2870 case Op_MemBarCPUOrder: return new(C) MemBarCPUOrderNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2871 case Op_Initialize: return new(C) InitializeNode(C, atp, pn); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2872 case Op_MemBarStoreStore: return new(C) MemBarStoreStoreNode(C, atp, pn); |
0 | 2873 default: ShouldNotReachHere(); return NULL; |
2874 } | |
2875 } | |
2876 | |
2877 //------------------------------Ideal------------------------------------------ | |
2878 // Return a node which is more "ideal" than the current node. Strip out | |
2879 // control copies | |
2880 Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2881 if (remove_dead_region(phase, can_reshape)) return this; |
4115 | 2882 // Don't bother trying to transform a dead node |
2883 if (in(0) && in(0)->is_top()) return NULL; | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2884 |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2885 // Eliminate volatile MemBars for scalar replaced objects. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2886 if (can_reshape && req() == (Precedent+1) && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2887 (Opcode() == Op_MemBarAcquire || Opcode() == Op_MemBarVolatile)) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2888 // Volatile field loads and stores. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2889 Node* my_mem = in(MemBarNode::Precedent); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2890 if (my_mem != NULL && my_mem->is_Mem()) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2891 const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2892 // Check for scalar replaced object reference. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2893 if( t_oop != NULL && t_oop->is_known_instance_field() && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2894 t_oop->offset() != Type::OffsetBot && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2895 t_oop->offset() != Type::OffsetTop) { |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2896 // Replace MemBar projections by its inputs. |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2897 PhaseIterGVN* igvn = phase->is_IterGVN(); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2898 igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory)); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2899 igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control)); |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2900 // Must return either the original node (now dead) or a new node |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2901 // (Do not return a top here, since that would break the uniqueness of top.) |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2902 return new (phase->C) ConINode(TypeInt::ZERO); |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2903 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2904 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2905 } |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
1080
diff
changeset
|
2906 return NULL; |
0 | 2907 } |
2908 | |
2909 //------------------------------Value------------------------------------------ | |
2910 const Type *MemBarNode::Value( PhaseTransform *phase ) const { | |
2911 if( !in(0) ) return Type::TOP; | |
2912 if( phase->type(in(0)) == Type::TOP ) | |
2913 return Type::TOP; | |
2914 return TypeTuple::MEMBAR; | |
2915 } | |
2916 | |
2917 //------------------------------match------------------------------------------ | |
2918 // Construct projections for memory. | |
2919 Node *MemBarNode::match( const ProjNode *proj, const Matcher *m ) { | |
2920 switch (proj->_con) { | |
2921 case TypeFunc::Control: | |
2922 case TypeFunc::Memory: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2923 return new (m->C) MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); |
0 | 2924 } |
2925 ShouldNotReachHere(); | |
2926 return NULL; | |
2927 } | |
2928 | |
2929 //===========================InitializeNode==================================== | |
2930 // SUMMARY: | |
2931 // This node acts as a memory barrier on raw memory, after some raw stores. | |
2932 // The 'cooked' oop value feeds from the Initialize, not the Allocation. | |
2933 // The Initialize can 'capture' suitably constrained stores as raw inits. | |
2934 // It can coalesce related raw stores into larger units (called 'tiles'). | |
2935 // It can avoid zeroing new storage for memory units which have raw inits. | |
2936 // At macro-expansion, it is marked 'complete', and does not optimize further. | |
2937 // | |
2938 // EXAMPLE: | |
2939 // The object 'new short[2]' occupies 16 bytes in a 32-bit machine. | |
2940 // ctl = incoming control; mem* = incoming memory | |
2941 // (Note: A star * on a memory edge denotes I/O and other standard edges.) | |
2942 // First allocate uninitialized memory and fill in the header: | |
2943 // alloc = (Allocate ctl mem* 16 #short[].klass ...) | |
2944 // ctl := alloc.Control; mem* := alloc.Memory* | |
2945 // rawmem = alloc.Memory; rawoop = alloc.RawAddress | |
2946 // Then initialize to zero the non-header parts of the raw memory block: | |
2947 // init = (Initialize alloc.Control alloc.Memory* alloc.RawAddress) | |
2948 // ctl := init.Control; mem.SLICE(#short[*]) := init.Memory | |
2949 // After the initialize node executes, the object is ready for service: | |
2950 // oop := (CheckCastPP init.Control alloc.RawAddress #short[]) | |
2951 // Suppose its body is immediately initialized as {1,2}: | |
2952 // store1 = (StoreC init.Control init.Memory (+ oop 12) 1) | |
2953 // store2 = (StoreC init.Control store1 (+ oop 14) 2) | |
2954 // mem.SLICE(#short[*]) := store2 | |
2955 // | |
2956 // DETAILS: | |
2957 // An InitializeNode collects and isolates object initialization after | |
2958 // an AllocateNode and before the next possible safepoint. As a | |
2959 // memory barrier (MemBarNode), it keeps critical stores from drifting | |
2960 // down past any safepoint or any publication of the allocation. | |
2961 // Before this barrier, a newly-allocated object may have uninitialized bits. | |
2962 // After this barrier, it may be treated as a real oop, and GC is allowed. | |
2963 // | |
2964 // The semantics of the InitializeNode include an implicit zeroing of | |
2965 // the new object from object header to the end of the object. | |
2966 // (The object header and end are determined by the AllocateNode.) | |
2967 // | |
2968 // Certain stores may be added as direct inputs to the InitializeNode. | |
2969 // These stores must update raw memory, and they must be to addresses | |
2970 // derived from the raw address produced by AllocateNode, and with | |
2971 // a constant offset. They must be ordered by increasing offset. | |
2972 // The first one is at in(RawStores), the last at in(req()-1). | |
2973 // Unlike most memory operations, they are not linked in a chain, | |
2974 // but are displayed in parallel as users of the rawmem output of | |
2975 // the allocation. | |
2976 // | |
2977 // (See comments in InitializeNode::capture_store, which continue | |
2978 // the example given above.) | |
2979 // | |
2980 // When the associated Allocate is macro-expanded, the InitializeNode | |
2981 // may be rewritten to optimize collected stores. A ClearArrayNode | |
2982 // may also be created at that point to represent any required zeroing. | |
2983 // The InitializeNode is then marked 'complete', prohibiting further | |
2984 // capturing of nearby memory operations. | |
2985 // | |
2986 // During macro-expansion, all captured initializations which store | |
605 | 2987 // constant values of 32 bits or smaller are coalesced (if advantageous) |
0 | 2988 // into larger 'tiles' 32 or 64 bits. This allows an object to be |
2989 // initialized in fewer memory operations. Memory words which are | |
2990 // covered by neither tiles nor non-constant stores are pre-zeroed | |
2991 // by explicit stores of zero. (The code shape happens to do all | |
2992 // zeroing first, then all other stores, with both sequences occurring | |
2993 // in order of ascending offsets.) | |
2994 // | |
2995 // Alternatively, code may be inserted between an AllocateNode and its | |
2996 // InitializeNode, to perform arbitrary initialization of the new object. | |
2997 // E.g., the object copying intrinsics insert complex data transfers here. | |
2998 // The initialization must then be marked as 'complete' disable the | |
2999 // built-in zeroing semantics and the collection of initializing stores. | |
3000 // | |
3001 // While an InitializeNode is incomplete, reads from the memory state | |
3002 // produced by it are optimizable if they match the control edge and | |
3003 // new oop address associated with the allocation/initialization. | |
3004 // They return a stored value (if the offset matches) or else zero. | |
3005 // A write to the memory state, if it matches control and address, | |
3006 // and if it is to a constant offset, may be 'captured' by the | |
3007 // InitializeNode. It is cloned as a raw memory operation and rewired | |
3008 // inside the initialization, to the raw oop produced by the allocation. | |
3009 // Operations on addresses which are provably distinct (e.g., to | |
3010 // other AllocateNodes) are allowed to bypass the initialization. | |
3011 // | |
3012 // The effect of all this is to consolidate object initialization | |
3013 // (both arrays and non-arrays, both piecewise and bulk) into a | |
3014 // single location, where it can be optimized as a unit. | |
3015 // | |
3016 // Only stores with an offset less than TrackedInitializationLimit words | |
3017 // will be considered for capture by an InitializeNode. This puts a | |
3018 // reasonable limit on the complexity of optimized initializations. | |
3019 | |
3020 //---------------------------InitializeNode------------------------------------ | |
3021 InitializeNode::InitializeNode(Compile* C, int adr_type, Node* rawoop) | |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
3022 : _is_complete(Incomplete), _does_not_escape(false), |
0 | 3023 MemBarNode(C, adr_type, rawoop) |
3024 { | |
3025 init_class_id(Class_Initialize); | |
3026 | |
3027 assert(adr_type == Compile::AliasIdxRaw, "only valid atp"); | |
3028 assert(in(RawAddress) == rawoop, "proper init"); | |
3029 // Note: allocation() can be NULL, for secondary initialization barriers | |
3030 } | |
3031 | |
3032 // Since this node is not matched, it will be processed by the | |
3033 // register allocator. Declare that there are no constraints | |
3034 // on the allocation of the RawAddress edge. | |
3035 const RegMask &InitializeNode::in_RegMask(uint idx) const { | |
3036 // This edge should be set to top, by the set_complete. But be conservative. | |
3037 if (idx == InitializeNode::RawAddress) | |
3038 return *(Compile::current()->matcher()->idealreg2spillmask[in(idx)->ideal_reg()]); | |
3039 return RegMask::Empty; | |
3040 } | |
3041 | |
3042 Node* InitializeNode::memory(uint alias_idx) { | |
3043 Node* mem = in(Memory); | |
3044 if (mem->is_MergeMem()) { | |
3045 return mem->as_MergeMem()->memory_at(alias_idx); | |
3046 } else { | |
3047 // incoming raw memory is not split | |
3048 return mem; | |
3049 } | |
3050 } | |
3051 | |
3052 bool InitializeNode::is_non_zero() { | |
3053 if (is_complete()) return false; | |
3054 remove_extra_zeroes(); | |
3055 return (req() > RawStores); | |
3056 } | |
3057 | |
3058 void InitializeNode::set_complete(PhaseGVN* phase) { | |
3059 assert(!is_complete(), "caller responsibility"); | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3902
diff
changeset
|
3060 _is_complete = Complete; |
0 | 3061 |
3062 // After this node is complete, it contains a bunch of | |
3063 // raw-memory initializations. There is no need for | |
3064 // it to have anything to do with non-raw memory effects. | |
3065 // Therefore, tell all non-raw users to re-optimize themselves, | |
3066 // after skipping the memory effects of this initialization. | |
3067 PhaseIterGVN* igvn = phase->is_IterGVN(); | |
3068 if (igvn) igvn->add_users_to_worklist(this); | |
3069 } | |
3070 | |
3071 // convenience function | |
3072 // return false if the init contains any stores already | |
3073 bool AllocateNode::maybe_set_complete(PhaseGVN* phase) { | |
3074 InitializeNode* init = initialization(); | |
3075 if (init == NULL || init->is_complete()) return false; | |
3076 init->remove_extra_zeroes(); | |
3077 // for now, if this allocation has already collected any inits, bail: | |
3078 if (init->is_non_zero()) return false; | |
3079 init->set_complete(phase); | |
3080 return true; | |
3081 } | |
3082 | |
3083 void InitializeNode::remove_extra_zeroes() { | |
3084 if (req() == RawStores) return; | |
3085 Node* zmem = zero_memory(); | |
3086 uint fill = RawStores; | |
3087 for (uint i = fill; i < req(); i++) { | |
3088 Node* n = in(i); | |
3089 if (n->is_top() || n == zmem) continue; // skip | |
3090 if (fill < i) set_req(fill, n); // compact | |
3091 ++fill; | |
3092 } | |
3093 // delete any empty spaces created: | |
3094 while (fill < req()) { | |
3095 del_req(fill); | |
3096 } | |
3097 } | |
3098 | |
3099 // Helper for remembering which stores go with which offsets. | |
3100 intptr_t InitializeNode::get_store_offset(Node* st, PhaseTransform* phase) { | |
3101 if (!st->is_Store()) return -1; // can happen to dead code via subsume_node | |
3102 intptr_t offset = -1; | |
3103 Node* base = AddPNode::Ideal_base_and_offset(st->in(MemNode::Address), | |
3104 phase, offset); | |
3105 if (base == NULL) return -1; // something is dead, | |
3106 if (offset < 0) return -1; // dead, dead | |
3107 return offset; | |
3108 } | |
3109 | |
3110 // Helper for proving that an initialization expression is | |
3111 // "simple enough" to be folded into an object initialization. | |
3112 // Attempts to prove that a store's initial value 'n' can be captured | |
3113 // within the initialization without creating a vicious cycle, such as: | |
3114 // { Foo p = new Foo(); p.next = p; } | |
3115 // True for constants and parameters and small combinations thereof. | |
3116 bool InitializeNode::detect_init_independence(Node* n, | |
3117 bool st_is_pinned, | |
3118 int& count) { | |
3119 if (n == NULL) return true; // (can this really happen?) | |
3120 if (n->is_Proj()) n = n->in(0); | |
3121 if (n == this) return false; // found a cycle | |
3122 if (n->is_Con()) return true; | |
3123 if (n->is_Start()) return true; // params, etc., are OK | |
3124 if (n->is_Root()) return true; // even better | |
3125 | |
3126 Node* ctl = n->in(0); | |
3127 if (ctl != NULL && !ctl->is_top()) { | |
3128 if (ctl->is_Proj()) ctl = ctl->in(0); | |
3129 if (ctl == this) return false; | |
3130 | |
3131 // If we already know that the enclosing memory op is pinned right after | |
3132 // the init, then any control flow that the store has picked up | |
3133 // must have preceded the init, or else be equal to the init. | |
3134 // Even after loop optimizations (which might change control edges) | |
3135 // a store is never pinned *before* the availability of its inputs. | |
119
d1a5218d7eaf
6686791: Side effect in NumberFormat tests with -server -Xcomp
kvn
parents:
113
diff
changeset
|
3136 if (!MemNode::all_controls_dominate(n, this)) |
0 | 3137 return false; // failed to prove a good control |
3138 | |
3139 } | |
3140 | |
3141 // Check data edges for possible dependencies on 'this'. | |
3142 if ((count += 1) > 20) return false; // complexity limit | |
3143 for (uint i = 1; i < n->req(); i++) { | |
3144 Node* m = n->in(i); | |
3145 if (m == NULL || m == n || m->is_top()) continue; | |
3146 uint first_i = n->find_edge(m); | |
3147 if (i != first_i) continue; // process duplicate edge just once | |
3148 if (!detect_init_independence(m, st_is_pinned, count)) { | |
3149 return false; | |
3150 } | |
3151 } | |
3152 | |
3153 return true; | |
3154 } | |
3155 | |
3156 // Here are all the checks a Store must pass before it can be moved into | |
3157 // an initialization. Returns zero if a check fails. | |
3158 // On success, returns the (constant) offset to which the store applies, | |
3159 // within the initialized memory. | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3160 intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) { |
0 | 3161 const int FAIL = 0; |
3162 if (st->req() != MemNode::ValueIn + 1) | |
3163 return FAIL; // an inscrutable StoreNode (card mark?) | |
3164 Node* ctl = st->in(MemNode::Control); | |
3165 if (!(ctl != NULL && ctl->is_Proj() && ctl->in(0) == this)) | |
3166 return FAIL; // must be unconditional after the initialization | |
3167 Node* mem = st->in(MemNode::Memory); | |
3168 if (!(mem->is_Proj() && mem->in(0) == this)) | |
3169 return FAIL; // must not be preceded by other stores | |
3170 Node* adr = st->in(MemNode::Address); | |
3171 intptr_t offset; | |
3172 AllocateNode* alloc = AllocateNode::Ideal_allocation(adr, phase, offset); | |
3173 if (alloc == NULL) | |
3174 return FAIL; // inscrutable address | |
3175 if (alloc != allocation()) | |
3176 return FAIL; // wrong allocation! (store needs to float up) | |
3177 Node* val = st->in(MemNode::ValueIn); | |
3178 int complexity_count = 0; | |
3179 if (!detect_init_independence(val, true, complexity_count)) | |
3180 return FAIL; // stored value must be 'simple enough' | |
3181 | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3182 // The Store can be captured only if nothing after the allocation |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3183 // and before the Store is using the memory location that the store |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3184 // overwrites. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3185 bool failed = false; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3186 // If is_complete_with_arraycopy() is true the shape of the graph is |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3187 // well defined and is safe so no need for extra checks. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3188 if (!is_complete_with_arraycopy()) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3189 // We are going to look at each use of the memory state following |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3190 // the allocation to make sure nothing reads the memory that the |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3191 // Store writes. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3192 const TypePtr* t_adr = phase->type(adr)->isa_ptr(); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3193 int alias_idx = phase->C->get_alias_index(t_adr); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3194 ResourceMark rm; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3195 Unique_Node_List mems; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3196 mems.push(mem); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3197 Node* unique_merge = NULL; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3198 for (uint next = 0; next < mems.size(); ++next) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3199 Node *m = mems.at(next); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3200 for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3201 Node *n = m->fast_out(j); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3202 if (n->outcnt() == 0) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3203 continue; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3204 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3205 if (n == st) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3206 continue; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3207 } else if (n->in(0) != NULL && n->in(0) != ctl) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3208 // If the control of this use is different from the control |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3209 // of the Store which is right after the InitializeNode then |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3210 // this node cannot be between the InitializeNode and the |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3211 // Store. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3212 continue; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3213 } else if (n->is_MergeMem()) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3214 if (n->as_MergeMem()->memory_at(alias_idx) == m) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3215 // We can hit a MergeMemNode (that will likely go away |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3216 // later) that is a direct use of the memory state |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3217 // following the InitializeNode on the same slice as the |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3218 // store node that we'd like to capture. We need to check |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3219 // the uses of the MergeMemNode. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3220 mems.push(n); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3221 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3222 } else if (n->is_Mem()) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3223 Node* other_adr = n->in(MemNode::Address); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3224 if (other_adr == adr) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3225 failed = true; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3226 break; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3227 } else { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3228 const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr(); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3229 if (other_t_adr != NULL) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3230 int other_alias_idx = phase->C->get_alias_index(other_t_adr); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3231 if (other_alias_idx == alias_idx) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3232 // A load from the same memory slice as the store right |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3233 // after the InitializeNode. We check the control of the |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3234 // object/array that is loaded from. If it's the same as |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3235 // the store control then we cannot capture the store. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3236 assert(!n->is_Store(), "2 stores to same slice on same control?"); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3237 Node* base = other_adr; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3238 assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name())); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3239 base = base->in(AddPNode::Base); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3240 if (base != NULL) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3241 base = base->uncast(); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3242 if (base->is_Proj() && base->in(0) == alloc) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3243 failed = true; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3244 break; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3245 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3246 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3247 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3248 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3249 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3250 } else { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3251 failed = true; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3252 break; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3253 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3254 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3255 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3256 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3257 if (failed) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3258 if (!can_reshape) { |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3259 // We decided we couldn't capture the store during parsing. We |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3260 // should try again during the next IGVN once the graph is |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3261 // cleaner. |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3262 phase->C->record_for_igvn(st); |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3263 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3264 return FAIL; |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3265 } |
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3266 |
0 | 3267 return offset; // success |
3268 } | |
3269 | |
3270 // Find the captured store in(i) which corresponds to the range | |
3271 // [start..start+size) in the initialized object. | |
3272 // If there is one, return its index i. If there isn't, return the | |
3273 // negative of the index where it should be inserted. | |
3274 // Return 0 if the queried range overlaps an initialization boundary | |
3275 // or if dead code is encountered. | |
3276 // If size_in_bytes is zero, do not bother with overlap checks. | |
3277 int InitializeNode::captured_store_insertion_point(intptr_t start, | |
3278 int size_in_bytes, | |
3279 PhaseTransform* phase) { | |
3280 const int FAIL = 0, MAX_STORE = BytesPerLong; | |
3281 | |
3282 if (is_complete()) | |
3283 return FAIL; // arraycopy got here first; punt | |
3284 | |
3285 assert(allocation() != NULL, "must be present"); | |
3286 | |
3287 // no negatives, no header fields: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3288 if (start < (intptr_t) allocation()->minimum_header_size()) return FAIL; |
0 | 3289 |
3290 // after a certain size, we bail out on tracking all the stores: | |
3291 intptr_t ti_limit = (TrackedInitializationLimit * HeapWordSize); | |
3292 if (start >= ti_limit) return FAIL; | |
3293 | |
3294 for (uint i = InitializeNode::RawStores, limit = req(); ; ) { | |
3295 if (i >= limit) return -(int)i; // not found; here is where to put it | |
3296 | |
3297 Node* st = in(i); | |
3298 intptr_t st_off = get_store_offset(st, phase); | |
3299 if (st_off < 0) { | |
3300 if (st != zero_memory()) { | |
3301 return FAIL; // bail out if there is dead garbage | |
3302 } | |
3303 } else if (st_off > start) { | |
3304 // ...we are done, since stores are ordered | |
3305 if (st_off < start + size_in_bytes) { | |
3306 return FAIL; // the next store overlaps | |
3307 } | |
3308 return -(int)i; // not found; here is where to put it | |
3309 } else if (st_off < start) { | |
3310 if (size_in_bytes != 0 && | |
3311 start < st_off + MAX_STORE && | |
3312 start < st_off + st->as_Store()->memory_size()) { | |
3313 return FAIL; // the previous store overlaps | |
3314 } | |
3315 } else { | |
3316 if (size_in_bytes != 0 && | |
3317 st->as_Store()->memory_size() != size_in_bytes) { | |
3318 return FAIL; // mismatched store size | |
3319 } | |
3320 return i; | |
3321 } | |
3322 | |
3323 ++i; | |
3324 } | |
3325 } | |
3326 | |
3327 // Look for a captured store which initializes at the offset 'start' | |
3328 // with the given size. If there is no such store, and no other | |
3329 // initialization interferes, then return zero_memory (the memory | |
3330 // projection of the AllocateNode). | |
3331 Node* InitializeNode::find_captured_store(intptr_t start, int size_in_bytes, | |
3332 PhaseTransform* phase) { | |
3333 assert(stores_are_sane(phase), ""); | |
3334 int i = captured_store_insertion_point(start, size_in_bytes, phase); | |
3335 if (i == 0) { | |
3336 return NULL; // something is dead | |
3337 } else if (i < 0) { | |
3338 return zero_memory(); // just primordial zero bits here | |
3339 } else { | |
3340 Node* st = in(i); // here is the store at this position | |
3341 assert(get_store_offset(st->as_Store(), phase) == start, "sanity"); | |
3342 return st; | |
3343 } | |
3344 } | |
3345 | |
3346 // Create, as a raw pointer, an address within my new object at 'offset'. | |
3347 Node* InitializeNode::make_raw_address(intptr_t offset, | |
3348 PhaseTransform* phase) { | |
3349 Node* addr = in(RawAddress); | |
3350 if (offset != 0) { | |
3351 Compile* C = phase->C; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3352 addr = phase->transform( new (C) AddPNode(C->top(), addr, |
0 | 3353 phase->MakeConX(offset)) ); |
3354 } | |
3355 return addr; | |
3356 } | |
3357 | |
3358 // Clone the given store, converting it into a raw store | |
3359 // initializing a field or element of my new object. | |
3360 // Caller is responsible for retiring the original store, | |
3361 // with subsume_node or the like. | |
3362 // | |
3363 // From the example above InitializeNode::InitializeNode, | |
3364 // here are the old stores to be captured: | |
3365 // store1 = (StoreC init.Control init.Memory (+ oop 12) 1) | |
3366 // store2 = (StoreC init.Control store1 (+ oop 14) 2) | |
3367 // | |
3368 // Here is the changed code; note the extra edges on init: | |
3369 // alloc = (Allocate ...) | |
3370 // rawoop = alloc.RawAddress | |
3371 // rawstore1 = (StoreC alloc.Control alloc.Memory (+ rawoop 12) 1) | |
3372 // rawstore2 = (StoreC alloc.Control alloc.Memory (+ rawoop 14) 2) | |
3373 // init = (Initialize alloc.Control alloc.Memory rawoop | |
3374 // rawstore1 rawstore2) | |
3375 // | |
3376 Node* InitializeNode::capture_store(StoreNode* st, intptr_t start, | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3377 PhaseTransform* phase, bool can_reshape) { |
0 | 3378 assert(stores_are_sane(phase), ""); |
3379 | |
3380 if (start < 0) return NULL; | |
8116
6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
roland
parents:
7637
diff
changeset
|
3381 assert(can_capture_store(st, phase, can_reshape) == start, "sanity"); |
0 | 3382 |
3383 Compile* C = phase->C; | |
3384 int size_in_bytes = st->memory_size(); | |
3385 int i = captured_store_insertion_point(start, size_in_bytes, phase); | |
3386 if (i == 0) return NULL; // bail out | |
3387 Node* prev_mem = NULL; // raw memory for the captured store | |
3388 if (i > 0) { | |
3389 prev_mem = in(i); // there is a pre-existing store under this one | |
3390 set_req(i, C->top()); // temporarily disconnect it | |
3391 // See StoreNode::Ideal 'st->outcnt() == 1' for the reason to disconnect. | |
3392 } else { | |
3393 i = -i; // no pre-existing store | |
3394 prev_mem = zero_memory(); // a slice of the newly allocated object | |
3395 if (i > InitializeNode::RawStores && in(i-1) == prev_mem) | |
3396 set_req(--i, C->top()); // reuse this edge; it has been folded away | |
3397 else | |
3398 ins_req(i, C->top()); // build a new edge | |
3399 } | |
3400 Node* new_st = st->clone(); | |
3401 new_st->set_req(MemNode::Control, in(Control)); | |
3402 new_st->set_req(MemNode::Memory, prev_mem); | |
3403 new_st->set_req(MemNode::Address, make_raw_address(start, phase)); | |
3404 new_st = phase->transform(new_st); | |
3405 | |
3406 // At this point, new_st might have swallowed a pre-existing store | |
3407 // at the same offset, or perhaps new_st might have disappeared, | |
3408 // if it redundantly stored the same value (or zero to fresh memory). | |
3409 | |
3410 // In any case, wire it in: | |
3411 set_req(i, new_st); | |
3412 | |
3413 // The caller may now kill the old guy. | |
3414 DEBUG_ONLY(Node* check_st = find_captured_store(start, size_in_bytes, phase)); | |
3415 assert(check_st == new_st || check_st == NULL, "must be findable"); | |
3416 assert(!is_complete(), ""); | |
3417 return new_st; | |
3418 } | |
3419 | |
3420 static bool store_constant(jlong* tiles, int num_tiles, | |
3421 intptr_t st_off, int st_size, | |
3422 jlong con) { | |
3423 if ((st_off & (st_size-1)) != 0) | |
3424 return false; // strange store offset (assume size==2**N) | |
3425 address addr = (address)tiles + st_off; | |
3426 assert(st_off >= 0 && addr+st_size <= (address)&tiles[num_tiles], "oob"); | |
3427 switch (st_size) { | |
3428 case sizeof(jbyte): *(jbyte*) addr = (jbyte) con; break; | |
3429 case sizeof(jchar): *(jchar*) addr = (jchar) con; break; | |
3430 case sizeof(jint): *(jint*) addr = (jint) con; break; | |
3431 case sizeof(jlong): *(jlong*) addr = (jlong) con; break; | |
3432 default: return false; // strange store size (detect size!=2**N here) | |
3433 } | |
3434 return true; // return success to caller | |
3435 } | |
3436 | |
3437 // Coalesce subword constants into int constants and possibly | |
3438 // into long constants. The goal, if the CPU permits, | |
3439 // is to initialize the object with a small number of 64-bit tiles. | |
3440 // Also, convert floating-point constants to bit patterns. | |
3441 // Non-constants are not relevant to this pass. | |
3442 // | |
3443 // In terms of the running example on InitializeNode::InitializeNode | |
3444 // and InitializeNode::capture_store, here is the transformation | |
3445 // of rawstore1 and rawstore2 into rawstore12: | |
3446 // alloc = (Allocate ...) | |
3447 // rawoop = alloc.RawAddress | |
3448 // tile12 = 0x00010002 | |
3449 // rawstore12 = (StoreI alloc.Control alloc.Memory (+ rawoop 12) tile12) | |
3450 // init = (Initialize alloc.Control alloc.Memory rawoop rawstore12) | |
3451 // | |
3452 void | |
3453 InitializeNode::coalesce_subword_stores(intptr_t header_size, | |
3454 Node* size_in_bytes, | |
3455 PhaseGVN* phase) { | |
3456 Compile* C = phase->C; | |
3457 | |
3458 assert(stores_are_sane(phase), ""); | |
3459 // Note: After this pass, they are not completely sane, | |
3460 // since there may be some overlaps. | |
3461 | |
3462 int old_subword = 0, old_long = 0, new_int = 0, new_long = 0; | |
3463 | |
3464 intptr_t ti_limit = (TrackedInitializationLimit * HeapWordSize); | |
3465 intptr_t size_limit = phase->find_intptr_t_con(size_in_bytes, ti_limit); | |
3466 size_limit = MIN2(size_limit, ti_limit); | |
3467 size_limit = align_size_up(size_limit, BytesPerLong); | |
3468 int num_tiles = size_limit / BytesPerLong; | |
3469 | |
3470 // allocate space for the tile map: | |
3471 const int small_len = DEBUG_ONLY(true ? 3 :) 30; // keep stack frames small | |
3472 jlong tiles_buf[small_len]; | |
3473 Node* nodes_buf[small_len]; | |
3474 jlong inits_buf[small_len]; | |
3475 jlong* tiles = ((num_tiles <= small_len) ? &tiles_buf[0] | |
3476 : NEW_RESOURCE_ARRAY(jlong, num_tiles)); | |
3477 Node** nodes = ((num_tiles <= small_len) ? &nodes_buf[0] | |
3478 : NEW_RESOURCE_ARRAY(Node*, num_tiles)); | |
3479 jlong* inits = ((num_tiles <= small_len) ? &inits_buf[0] | |
3480 : NEW_RESOURCE_ARRAY(jlong, num_tiles)); | |
3481 // tiles: exact bitwise model of all primitive constants | |
3482 // nodes: last constant-storing node subsumed into the tiles model | |
3483 // inits: which bytes (in each tile) are touched by any initializations | |
3484 | |
3485 //// Pass A: Fill in the tile model with any relevant stores. | |
3486 | |
3487 Copy::zero_to_bytes(tiles, sizeof(tiles[0]) * num_tiles); | |
3488 Copy::zero_to_bytes(nodes, sizeof(nodes[0]) * num_tiles); | |
3489 Copy::zero_to_bytes(inits, sizeof(inits[0]) * num_tiles); | |
3490 Node* zmem = zero_memory(); // initially zero memory state | |
3491 for (uint i = InitializeNode::RawStores, limit = req(); i < limit; i++) { | |
3492 Node* st = in(i); | |
3493 intptr_t st_off = get_store_offset(st, phase); | |
3494 | |
3495 // Figure out the store's offset and constant value: | |
3496 if (st_off < header_size) continue; //skip (ignore header) | |
3497 if (st->in(MemNode::Memory) != zmem) continue; //skip (odd store chain) | |
3498 int st_size = st->as_Store()->memory_size(); | |
3499 if (st_off + st_size > size_limit) break; | |
3500 | |
3501 // Record which bytes are touched, whether by constant or not. | |
3502 if (!store_constant(inits, num_tiles, st_off, st_size, (jlong) -1)) | |
3503 continue; // skip (strange store size) | |
3504 | |
3505 const Type* val = phase->type(st->in(MemNode::ValueIn)); | |
3506 if (!val->singleton()) continue; //skip (non-con store) | |
3507 BasicType type = val->basic_type(); | |
3508 | |
3509 jlong con = 0; | |
3510 switch (type) { | |
3511 case T_INT: con = val->is_int()->get_con(); break; | |
3512 case T_LONG: con = val->is_long()->get_con(); break; | |
3513 case T_FLOAT: con = jint_cast(val->getf()); break; | |
3514 case T_DOUBLE: con = jlong_cast(val->getd()); break; | |
3515 default: continue; //skip (odd store type) | |
3516 } | |
3517 | |
3518 if (type == T_LONG && Matcher::isSimpleConstant64(con) && | |
3519 st->Opcode() == Op_StoreL) { | |
3520 continue; // This StoreL is already optimal. | |
3521 } | |
3522 | |
3523 // Store down the constant. | |
3524 store_constant(tiles, num_tiles, st_off, st_size, con); | |
3525 | |
3526 intptr_t j = st_off >> LogBytesPerLong; | |
3527 | |
3528 if (type == T_INT && st_size == BytesPerInt | |
3529 && (st_off & BytesPerInt) == BytesPerInt) { | |
3530 jlong lcon = tiles[j]; | |
3531 if (!Matcher::isSimpleConstant64(lcon) && | |
3532 st->Opcode() == Op_StoreI) { | |
3533 // This StoreI is already optimal by itself. | |
3534 jint* intcon = (jint*) &tiles[j]; | |
3535 intcon[1] = 0; // undo the store_constant() | |
3536 | |
3537 // If the previous store is also optimal by itself, back up and | |
3538 // undo the action of the previous loop iteration... if we can. | |
3539 // But if we can't, just let the previous half take care of itself. | |
3540 st = nodes[j]; | |
3541 st_off -= BytesPerInt; | |
3542 con = intcon[0]; | |
3543 if (con != 0 && st != NULL && st->Opcode() == Op_StoreI) { | |
3544 assert(st_off >= header_size, "still ignoring header"); | |
3545 assert(get_store_offset(st, phase) == st_off, "must be"); | |
3546 assert(in(i-1) == zmem, "must be"); | |
3547 DEBUG_ONLY(const Type* tcon = phase->type(st->in(MemNode::ValueIn))); | |
3548 assert(con == tcon->is_int()->get_con(), "must be"); | |
3549 // Undo the effects of the previous loop trip, which swallowed st: | |
3550 intcon[0] = 0; // undo store_constant() | |
3551 set_req(i-1, st); // undo set_req(i, zmem) | |
3552 nodes[j] = NULL; // undo nodes[j] = st | |
3553 --old_subword; // undo ++old_subword | |
3554 } | |
3555 continue; // This StoreI is already optimal. | |
3556 } | |
3557 } | |
3558 | |
3559 // This store is not needed. | |
3560 set_req(i, zmem); | |
3561 nodes[j] = st; // record for the moment | |
3562 if (st_size < BytesPerLong) // something has changed | |
3563 ++old_subword; // includes int/float, but who's counting... | |
3564 else ++old_long; | |
3565 } | |
3566 | |
3567 if ((old_subword + old_long) == 0) | |
3568 return; // nothing more to do | |
3569 | |
3570 //// Pass B: Convert any non-zero tiles into optimal constant stores. | |
3571 // Be sure to insert them before overlapping non-constant stores. | |
3572 // (E.g., byte[] x = { 1,2,y,4 } => x[int 0] = 0x01020004, x[2]=y.) | |
3573 for (int j = 0; j < num_tiles; j++) { | |
3574 jlong con = tiles[j]; | |
3575 jlong init = inits[j]; | |
3576 if (con == 0) continue; | |
3577 jint con0, con1; // split the constant, address-wise | |
3578 jint init0, init1; // split the init map, address-wise | |
3579 { union { jlong con; jint intcon[2]; } u; | |
3580 u.con = con; | |
3581 con0 = u.intcon[0]; | |
3582 con1 = u.intcon[1]; | |
3583 u.con = init; | |
3584 init0 = u.intcon[0]; | |
3585 init1 = u.intcon[1]; | |
3586 } | |
3587 | |
3588 Node* old = nodes[j]; | |
3589 assert(old != NULL, "need the prior store"); | |
3590 intptr_t offset = (j * BytesPerLong); | |
3591 | |
3592 bool split = !Matcher::isSimpleConstant64(con); | |
3593 | |
3594 if (offset < header_size) { | |
3595 assert(offset + BytesPerInt >= header_size, "second int counts"); | |
3596 assert(*(jint*)&tiles[j] == 0, "junk in header"); | |
3597 split = true; // only the second word counts | |
3598 // Example: int a[] = { 42 ... } | |
3599 } else if (con0 == 0 && init0 == -1) { | |
3600 split = true; // first word is covered by full inits | |
3601 // Example: int a[] = { ... foo(), 42 ... } | |
3602 } else if (con1 == 0 && init1 == -1) { | |
3603 split = true; // second word is covered by full inits | |
3604 // Example: int a[] = { ... 42, foo() ... } | |
3605 } | |
3606 | |
3607 // Here's a case where init0 is neither 0 nor -1: | |
3608 // byte a[] = { ... 0,0,foo(),0, 0,0,0,42 ... } | |
3609 // Assuming big-endian memory, init0, init1 are 0x0000FF00, 0x000000FF. | |
3610 // In this case the tile is not split; it is (jlong)42. | |
3611 // The big tile is stored down, and then the foo() value is inserted. | |
3612 // (If there were foo(),foo() instead of foo(),0, init0 would be -1.) | |
3613 | |
3614 Node* ctl = old->in(MemNode::Control); | |
3615 Node* adr = make_raw_address(offset, phase); | |
3616 const TypePtr* atp = TypeRawPtr::BOTTOM; | |
3617 | |
3618 // One or two coalesced stores to plop down. | |
3619 Node* st[2]; | |
3620 intptr_t off[2]; | |
3621 int nst = 0; | |
3622 if (!split) { | |
3623 ++new_long; | |
3624 off[nst] = offset; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3625 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, |
0 | 3626 phase->longcon(con), T_LONG); |
3627 } else { | |
3628 // Omit either if it is a zero. | |
3629 if (con0 != 0) { | |
3630 ++new_int; | |
3631 off[nst] = offset; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3632 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, |
0 | 3633 phase->intcon(con0), T_INT); |
3634 } | |
3635 if (con1 != 0) { | |
3636 ++new_int; | |
3637 offset += BytesPerInt; | |
3638 adr = make_raw_address(offset, phase); | |
3639 off[nst] = offset; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3640 st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, |
0 | 3641 phase->intcon(con1), T_INT); |
3642 } | |
3643 } | |
3644 | |
3645 // Insert second store first, then the first before the second. | |
3646 // Insert each one just before any overlapping non-constant stores. | |
3647 while (nst > 0) { | |
3648 Node* st1 = st[--nst]; | |
3649 C->copy_node_notes_to(st1, old); | |
3650 st1 = phase->transform(st1); | |
3651 offset = off[nst]; | |
3652 assert(offset >= header_size, "do not smash header"); | |
3653 int ins_idx = captured_store_insertion_point(offset, /*size:*/0, phase); | |
3654 guarantee(ins_idx != 0, "must re-insert constant store"); | |
3655 if (ins_idx < 0) ins_idx = -ins_idx; // never overlap | |
3656 if (ins_idx > InitializeNode::RawStores && in(ins_idx-1) == zmem) | |
3657 set_req(--ins_idx, st1); | |
3658 else | |
3659 ins_req(ins_idx, st1); | |
3660 } | |
3661 } | |
3662 | |
3663 if (PrintCompilation && WizardMode) | |
3664 tty->print_cr("Changed %d/%d subword/long constants into %d/%d int/long", | |
3665 old_subword, old_long, new_int, new_long); | |
3666 if (C->log() != NULL) | |
3667 C->log()->elem("comment that='%d/%d subword/long to %d/%d int/long'", | |
3668 old_subword, old_long, new_int, new_long); | |
3669 | |
3670 // Clean up any remaining occurrences of zmem: | |
3671 remove_extra_zeroes(); | |
3672 } | |
3673 | |
3674 // Explore forward from in(start) to find the first fully initialized | |
3675 // word, and return its offset. Skip groups of subword stores which | |
3676 // together initialize full words. If in(start) is itself part of a | |
3677 // fully initialized word, return the offset of in(start). If there | |
3678 // are no following full-word stores, or if something is fishy, return | |
3679 // a negative value. | |
3680 intptr_t InitializeNode::find_next_fullword_store(uint start, PhaseGVN* phase) { | |
3681 int int_map = 0; | |
3682 intptr_t int_map_off = 0; | |
3683 const int FULL_MAP = right_n_bits(BytesPerInt); // the int_map we hope for | |
3684 | |
3685 for (uint i = start, limit = req(); i < limit; i++) { | |
3686 Node* st = in(i); | |
3687 | |
3688 intptr_t st_off = get_store_offset(st, phase); | |
3689 if (st_off < 0) break; // return conservative answer | |
3690 | |
3691 int st_size = st->as_Store()->memory_size(); | |
3692 if (st_size >= BytesPerInt && (st_off % BytesPerInt) == 0) { | |
3693 return st_off; // we found a complete word init | |
3694 } | |
3695 | |
3696 // update the map: | |
3697 | |
3698 intptr_t this_int_off = align_size_down(st_off, BytesPerInt); | |
3699 if (this_int_off != int_map_off) { | |
3700 // reset the map: | |
3701 int_map = 0; | |
3702 int_map_off = this_int_off; | |
3703 } | |
3704 | |
3705 int subword_off = st_off - this_int_off; | |
3706 int_map |= right_n_bits(st_size) << subword_off; | |
3707 if ((int_map & FULL_MAP) == FULL_MAP) { | |
3708 return this_int_off; // we found a complete word init | |
3709 } | |
3710 | |
3711 // Did this store hit or cross the word boundary? | |
3712 intptr_t next_int_off = align_size_down(st_off + st_size, BytesPerInt); | |
3713 if (next_int_off == this_int_off + BytesPerInt) { | |
3714 // We passed the current int, without fully initializing it. | |
3715 int_map_off = next_int_off; | |
3716 int_map >>= BytesPerInt; | |
3717 } else if (next_int_off > this_int_off + BytesPerInt) { | |
3718 // We passed the current and next int. | |
3719 return this_int_off + BytesPerInt; | |
3720 } | |
3721 } | |
3722 | |
3723 return -1; | |
3724 } | |
3725 | |
3726 | |
3727 // Called when the associated AllocateNode is expanded into CFG. | |
3728 // At this point, we may perform additional optimizations. | |
3729 // Linearize the stores by ascending offset, to make memory | |
3730 // activity as coherent as possible. | |
3731 Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, | |
3732 intptr_t header_size, | |
3733 Node* size_in_bytes, | |
3734 PhaseGVN* phase) { | |
3735 assert(!is_complete(), "not already complete"); | |
3736 assert(stores_are_sane(phase), ""); | |
3737 assert(allocation() != NULL, "must be present"); | |
3738 | |
3739 remove_extra_zeroes(); | |
3740 | |
3741 if (ReduceFieldZeroing || ReduceBulkZeroing) | |
3742 // reduce instruction count for common initialization patterns | |
3743 coalesce_subword_stores(header_size, size_in_bytes, phase); | |
3744 | |
3745 Node* zmem = zero_memory(); // initially zero memory state | |
3746 Node* inits = zmem; // accumulating a linearized chain of inits | |
3747 #ifdef ASSERT | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3748 intptr_t first_offset = allocation()->minimum_header_size(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3749 intptr_t last_init_off = first_offset; // previous init offset |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3750 intptr_t last_init_end = first_offset; // previous init offset+size |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3751 intptr_t last_tile_end = first_offset; // previous tile offset+size |
0 | 3752 #endif |
3753 intptr_t zeroes_done = header_size; | |
3754 | |
3755 bool do_zeroing = true; // we might give up if inits are very sparse | |
3756 int big_init_gaps = 0; // how many large gaps have we seen? | |
3757 | |
3758 if (ZeroTLAB) do_zeroing = false; | |
3759 if (!ReduceFieldZeroing && !ReduceBulkZeroing) do_zeroing = false; | |
3760 | |
3761 for (uint i = InitializeNode::RawStores, limit = req(); i < limit; i++) { | |
3762 Node* st = in(i); | |
3763 intptr_t st_off = get_store_offset(st, phase); | |
3764 if (st_off < 0) | |
3765 break; // unknown junk in the inits | |
3766 if (st->in(MemNode::Memory) != zmem) | |
3767 break; // complicated store chains somehow in list | |
3768 | |
3769 int st_size = st->as_Store()->memory_size(); | |
3770 intptr_t next_init_off = st_off + st_size; | |
3771 | |
3772 if (do_zeroing && zeroes_done < next_init_off) { | |
3773 // See if this store needs a zero before it or under it. | |
3774 intptr_t zeroes_needed = st_off; | |
3775 | |
3776 if (st_size < BytesPerInt) { | |
3777 // Look for subword stores which only partially initialize words. | |
3778 // If we find some, we must lay down some word-level zeroes first, | |
3779 // underneath the subword stores. | |
3780 // | |
3781 // Examples: | |
3782 // byte[] a = { p,q,r,s } => a[0]=p,a[1]=q,a[2]=r,a[3]=s | |
3783 // byte[] a = { x,y,0,0 } => a[0..3] = 0, a[0]=x,a[1]=y | |
3784 // byte[] a = { 0,0,z,0 } => a[0..3] = 0, a[2]=z | |
3785 // | |
3786 // Note: coalesce_subword_stores may have already done this, | |
3787 // if it was prompted by constant non-zero subword initializers. | |
3788 // But this case can still arise with non-constant stores. | |
3789 | |
3790 intptr_t next_full_store = find_next_fullword_store(i, phase); | |
3791 | |
3792 // In the examples above: | |
3793 // in(i) p q r s x y z | |
3794 // st_off 12 13 14 15 12 13 14 | |
3795 // st_size 1 1 1 1 1 1 1 | |
3796 // next_full_s. 12 16 16 16 16 16 16 | |
3797 // z's_done 12 16 16 16 12 16 12 | |
3798 // z's_needed 12 16 16 16 16 16 16 | |
3799 // zsize 0 0 0 0 4 0 4 | |
3800 if (next_full_store < 0) { | |
3801 // Conservative tack: Zero to end of current word. | |
3802 zeroes_needed = align_size_up(zeroes_needed, BytesPerInt); | |
3803 } else { | |
3804 // Zero to beginning of next fully initialized word. | |
3805 // Or, don't zero at all, if we are already in that word. | |
3806 assert(next_full_store >= zeroes_needed, "must go forward"); | |
3807 assert((next_full_store & (BytesPerInt-1)) == 0, "even boundary"); | |
3808 zeroes_needed = next_full_store; | |
3809 } | |
3810 } | |
3811 | |
3812 if (zeroes_needed > zeroes_done) { | |
3813 intptr_t zsize = zeroes_needed - zeroes_done; | |
3814 // Do some incremental zeroing on rawmem, in parallel with inits. | |
3815 zeroes_done = align_size_down(zeroes_done, BytesPerInt); | |
3816 rawmem = ClearArrayNode::clear_memory(rawctl, rawmem, rawptr, | |
3817 zeroes_done, zeroes_needed, | |
3818 phase); | |
3819 zeroes_done = zeroes_needed; | |
3820 if (zsize > Matcher::init_array_short_size && ++big_init_gaps > 2) | |
3821 do_zeroing = false; // leave the hole, next time | |
3822 } | |
3823 } | |
3824 | |
3825 // Collect the store and move on: | |
3826 st->set_req(MemNode::Memory, inits); | |
3827 inits = st; // put it on the linearized chain | |
3828 set_req(i, zmem); // unhook from previous position | |
3829 | |
3830 if (zeroes_done == st_off) | |
3831 zeroes_done = next_init_off; | |
3832 | |
3833 assert(!do_zeroing || zeroes_done >= next_init_off, "don't miss any"); | |
3834 | |
3835 #ifdef ASSERT | |
3836 // Various order invariants. Weaker than stores_are_sane because | |
3837 // a large constant tile can be filled in by smaller non-constant stores. | |
3838 assert(st_off >= last_init_off, "inits do not reverse"); | |
3839 last_init_off = st_off; | |
3840 const Type* val = NULL; | |
3841 if (st_size >= BytesPerInt && | |
3842 (val = phase->type(st->in(MemNode::ValueIn)))->singleton() && | |
3843 (int)val->basic_type() < (int)T_OBJECT) { | |
3844 assert(st_off >= last_tile_end, "tiles do not overlap"); | |
3845 assert(st_off >= last_init_end, "tiles do not overwrite inits"); | |
3846 last_tile_end = MAX2(last_tile_end, next_init_off); | |
3847 } else { | |
3848 intptr_t st_tile_end = align_size_up(next_init_off, BytesPerLong); | |
3849 assert(st_tile_end >= last_tile_end, "inits stay with tiles"); | |
3850 assert(st_off >= last_init_end, "inits do not overlap"); | |
3851 last_init_end = next_init_off; // it's a non-tile | |
3852 } | |
3853 #endif //ASSERT | |
3854 } | |
3855 | |
3856 remove_extra_zeroes(); // clear out all the zmems left over | |
3857 add_req(inits); | |
3858 | |
3859 if (!ZeroTLAB) { | |
3860 // If anything remains to be zeroed, zero it all now. | |
3861 zeroes_done = align_size_down(zeroes_done, BytesPerInt); | |
3862 // if it is the last unused 4 bytes of an instance, forget about it | |
3863 intptr_t size_limit = phase->find_intptr_t_con(size_in_bytes, max_jint); | |
3864 if (zeroes_done + BytesPerLong >= size_limit) { | |
3865 assert(allocation() != NULL, ""); | |
2004
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3866 if (allocation()->Opcode() == Op_Allocate) { |
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3867 Node* klass_node = allocation()->in(AllocateNode::KlassNode); |
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3868 ciKlass* k = phase->type(klass_node)->is_klassptr()->klass(); |
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3869 if (zeroes_done == k->layout_helper()) |
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3870 zeroes_done = size_limit; |
4da76e32c0be
7002666: eclipse CDT projects crash with compressed oops
never
parents:
1972
diff
changeset
|
3871 } |
0 | 3872 } |
3873 if (zeroes_done < size_limit) { | |
3874 rawmem = ClearArrayNode::clear_memory(rawctl, rawmem, rawptr, | |
3875 zeroes_done, size_in_bytes, phase); | |
3876 } | |
3877 } | |
3878 | |
3879 set_complete(phase); | |
3880 return rawmem; | |
3881 } | |
3882 | |
3883 | |
3884 #ifdef ASSERT | |
3885 bool InitializeNode::stores_are_sane(PhaseTransform* phase) { | |
3886 if (is_complete()) | |
3887 return true; // stores could be anything at this point | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3888 assert(allocation() != NULL, "must be present"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
82
diff
changeset
|
3889 intptr_t last_off = allocation()->minimum_header_size(); |
0 | 3890 for (uint i = InitializeNode::RawStores; i < req(); i++) { |
3891 Node* st = in(i); | |
3892 intptr_t st_off = get_store_offset(st, phase); | |
3893 if (st_off < 0) continue; // ignore dead garbage | |
3894 if (last_off > st_off) { | |
3895 tty->print_cr("*** bad store offset at %d: %d > %d", i, last_off, st_off); | |
3896 this->dump(2); | |
3897 assert(false, "ascending store offsets"); | |
3898 return false; | |
3899 } | |
3900 last_off = st_off + st->as_Store()->memory_size(); | |
3901 } | |
3902 return true; | |
3903 } | |
3904 #endif //ASSERT | |
3905 | |
3906 | |
3907 | |
3908 | |
3909 //============================MergeMemNode===================================== | |
3910 // | |
3911 // SEMANTICS OF MEMORY MERGES: A MergeMem is a memory state assembled from several | |
3912 // contributing store or call operations. Each contributor provides the memory | |
3913 // state for a particular "alias type" (see Compile::alias_type). For example, | |
3914 // if a MergeMem has an input X for alias category #6, then any memory reference | |
3915 // to alias category #6 may use X as its memory state input, as an exact equivalent | |
3916 // to using the MergeMem as a whole. | |
3917 // Load<6>( MergeMem(<6>: X, ...), p ) <==> Load<6>(X,p) | |
3918 // | |
3919 // (Here, the <N> notation gives the index of the relevant adr_type.) | |
3920 // | |
3921 // In one special case (and more cases in the future), alias categories overlap. | |
3922 // The special alias category "Bot" (Compile::AliasIdxBot) includes all memory | |
3923 // states. Therefore, if a MergeMem has only one contributing input W for Bot, | |
3924 // it is exactly equivalent to that state W: | |
3925 // MergeMem(<Bot>: W) <==> W | |
3926 // | |
3927 // Usually, the merge has more than one input. In that case, where inputs | |
3928 // overlap (i.e., one is Bot), the narrower alias type determines the memory | |
3929 // state for that type, and the wider alias type (Bot) fills in everywhere else: | |
3930 // Load<5>( MergeMem(<Bot>: W, <6>: X), p ) <==> Load<5>(W,p) | |
3931 // Load<6>( MergeMem(<Bot>: W, <6>: X), p ) <==> Load<6>(X,p) | |
3932 // | |
3933 // A merge can take a "wide" memory state as one of its narrow inputs. | |
3934 // This simply means that the merge observes out only the relevant parts of | |
3935 // the wide input. That is, wide memory states arriving at narrow merge inputs | |
3936 // are implicitly "filtered" or "sliced" as necessary. (This is rare.) | |
3937 // | |
3938 // These rules imply that MergeMem nodes may cascade (via their <Bot> links), | |
3939 // and that memory slices "leak through": | |
3940 // MergeMem(<Bot>: MergeMem(<Bot>: W, <7>: Y)) <==> MergeMem(<Bot>: W, <7>: Y) | |
3941 // | |
3942 // But, in such a cascade, repeated memory slices can "block the leak": | |
3943 // MergeMem(<Bot>: MergeMem(<Bot>: W, <7>: Y), <7>: Y') <==> MergeMem(<Bot>: W, <7>: Y') | |
3944 // | |
3945 // In the last example, Y is not part of the combined memory state of the | |
3946 // outermost MergeMem. The system must, of course, prevent unschedulable | |
3947 // memory states from arising, so you can be sure that the state Y is somehow | |
3948 // a precursor to state Y'. | |
3949 // | |
3950 // | |
3951 // REPRESENTATION OF MEMORY MERGES: The indexes used to address the Node::in array | |
3952 // of each MergeMemNode array are exactly the numerical alias indexes, including | |
3953 // but not limited to AliasIdxTop, AliasIdxBot, and AliasIdxRaw. The functions | |
3954 // Compile::alias_type (and kin) produce and manage these indexes. | |
3955 // | |
3956 // By convention, the value of in(AliasIdxTop) (i.e., in(1)) is always the top node. | |
3957 // (Note that this provides quick access to the top node inside MergeMem methods, | |
3958 // without the need to reach out via TLS to Compile::current.) | |
3959 // | |
3960 // As a consequence of what was just described, a MergeMem that represents a full | |
3961 // memory state has an edge in(AliasIdxBot) which is a "wide" memory state, | |
3962 // containing all alias categories. | |
3963 // | |
3964 // MergeMem nodes never (?) have control inputs, so in(0) is NULL. | |
3965 // | |
3966 // All other edges in(N) (including in(AliasIdxRaw), which is in(3)) are either | |
3967 // a memory state for the alias type <N>, or else the top node, meaning that | |
3968 // there is no particular input for that alias type. Note that the length of | |
3969 // a MergeMem is variable, and may be extended at any time to accommodate new | |
3970 // memory states at larger alias indexes. When merges grow, they are of course | |
3971 // filled with "top" in the unused in() positions. | |
3972 // | |
3973 // This use of top is named "empty_memory()", or "empty_mem" (no-memory) as a variable. | |
3974 // (Top was chosen because it works smoothly with passes like GCM.) | |
3975 // | |
3976 // For convenience, we hardwire the alias index for TypeRawPtr::BOTTOM. (It is | |
3977 // the type of random VM bits like TLS references.) Since it is always the | |
3978 // first non-Bot memory slice, some low-level loops use it to initialize an | |
3979 // index variable: for (i = AliasIdxRaw; i < req(); i++). | |
3980 // | |
3981 // | |
3982 // ACCESSORS: There is a special accessor MergeMemNode::base_memory which returns | |
3983 // the distinguished "wide" state. The accessor MergeMemNode::memory_at(N) returns | |
3984 // the memory state for alias type <N>, or (if there is no particular slice at <N>, | |
3985 // it returns the base memory. To prevent bugs, memory_at does not accept <Top> | |
3986 // or <Bot> indexes. The iterator MergeMemStream provides robust iteration over | |
3987 // MergeMem nodes or pairs of such nodes, ensuring that the non-top edges are visited. | |
3988 // | |
3989 // %%%% We may get rid of base_memory as a separate accessor at some point; it isn't | |
3990 // really that different from the other memory inputs. An abbreviation called | |
3991 // "bot_memory()" for "memory_at(AliasIdxBot)" would keep code tidy. | |
3992 // | |
3993 // | |
3994 // PARTIAL MEMORY STATES: During optimization, MergeMem nodes may arise that represent | |
3995 // partial memory states. When a Phi splits through a MergeMem, the copy of the Phi | |
3996 // that "emerges though" the base memory will be marked as excluding the alias types | |
3997 // of the other (narrow-memory) copies which "emerged through" the narrow edges: | |
3998 // | |
3999 // Phi<Bot>(U, MergeMem(<Bot>: W, <8>: Y)) | |
4000 // ==Ideal=> MergeMem(<Bot>: Phi<Bot-8>(U, W), Phi<8>(U, Y)) | |
4001 // | |
4002 // This strange "subtraction" effect is necessary to ensure IGVN convergence. | |
4003 // (It is currently unimplemented.) As you can see, the resulting merge is | |
4004 // actually a disjoint union of memory states, rather than an overlay. | |
4005 // | |
4006 | |
4007 //------------------------------MergeMemNode----------------------------------- | |
4008 Node* MergeMemNode::make_empty_memory() { | |
4009 Node* empty_memory = (Node*) Compile::current()->top(); | |
4010 assert(empty_memory->is_top(), "correct sentinel identity"); | |
4011 return empty_memory; | |
4012 } | |
4013 | |
4014 MergeMemNode::MergeMemNode(Node *new_base) : Node(1+Compile::AliasIdxRaw) { | |
4015 init_class_id(Class_MergeMem); | |
4016 // all inputs are nullified in Node::Node(int) | |
4017 // set_input(0, NULL); // no control input | |
4018 | |
4019 // Initialize the edges uniformly to top, for starters. | |
4020 Node* empty_mem = make_empty_memory(); | |
4021 for (uint i = Compile::AliasIdxTop; i < req(); i++) { | |
4022 init_req(i,empty_mem); | |
4023 } | |
4024 assert(empty_memory() == empty_mem, ""); | |
4025 | |
4026 if( new_base != NULL && new_base->is_MergeMem() ) { | |
4027 MergeMemNode* mdef = new_base->as_MergeMem(); | |
4028 assert(mdef->empty_memory() == empty_mem, "consistent sentinels"); | |
4029 for (MergeMemStream mms(this, mdef); mms.next_non_empty2(); ) { | |
4030 mms.set_memory(mms.memory2()); | |
4031 } | |
4032 assert(base_memory() == mdef->base_memory(), ""); | |
4033 } else { | |
4034 set_base_memory(new_base); | |
4035 } | |
4036 } | |
4037 | |
4038 // Make a new, untransformed MergeMem with the same base as 'mem'. | |
4039 // If mem is itself a MergeMem, populate the result with the same edges. | |
4040 MergeMemNode* MergeMemNode::make(Compile* C, Node* mem) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4041 return new(C) MergeMemNode(mem); |
0 | 4042 } |
4043 | |
4044 //------------------------------cmp-------------------------------------------- | |
4045 uint MergeMemNode::hash() const { return NO_HASH; } | |
4046 uint MergeMemNode::cmp( const Node &n ) const { | |
4047 return (&n == this); // Always fail except on self | |
4048 } | |
4049 | |
4050 //------------------------------Identity--------------------------------------- | |
4051 Node* MergeMemNode::Identity(PhaseTransform *phase) { | |
4052 // Identity if this merge point does not record any interesting memory | |
4053 // disambiguations. | |
4054 Node* base_mem = base_memory(); | |
4055 Node* empty_mem = empty_memory(); | |
4056 if (base_mem != empty_mem) { // Memory path is not dead? | |
4057 for (uint i = Compile::AliasIdxRaw; i < req(); i++) { | |
4058 Node* mem = in(i); | |
4059 if (mem != empty_mem && mem != base_mem) { | |
4060 return this; // Many memory splits; no change | |
4061 } | |
4062 } | |
4063 } | |
4064 return base_mem; // No memory splits; ID on the one true input | |
4065 } | |
4066 | |
4067 //------------------------------Ideal------------------------------------------ | |
4068 // This method is invoked recursively on chains of MergeMem nodes | |
4069 Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
4070 // Remove chain'd MergeMems | |
4071 // | |
4072 // This is delicate, because the each "in(i)" (i >= Raw) is interpreted | |
4073 // relative to the "in(Bot)". Since we are patching both at the same time, | |
4074 // we have to be careful to read each "in(i)" relative to the old "in(Bot)", | |
4075 // but rewrite each "in(i)" relative to the new "in(Bot)". | |
4076 Node *progress = NULL; | |
4077 | |
4078 | |
4079 Node* old_base = base_memory(); | |
4080 Node* empty_mem = empty_memory(); | |
4081 if (old_base == empty_mem) | |
4082 return NULL; // Dead memory path. | |
4083 | |
4084 MergeMemNode* old_mbase; | |
4085 if (old_base != NULL && old_base->is_MergeMem()) | |
4086 old_mbase = old_base->as_MergeMem(); | |
4087 else | |
4088 old_mbase = NULL; | |
4089 Node* new_base = old_base; | |
4090 | |
4091 // simplify stacked MergeMems in base memory | |
4092 if (old_mbase) new_base = old_mbase->base_memory(); | |
4093 | |
4094 // the base memory might contribute new slices beyond my req() | |
4095 if (old_mbase) grow_to_match(old_mbase); | |
4096 | |
4097 // Look carefully at the base node if it is a phi. | |
4098 PhiNode* phi_base; | |
4099 if (new_base != NULL && new_base->is_Phi()) | |
4100 phi_base = new_base->as_Phi(); | |
4101 else | |
4102 phi_base = NULL; | |
4103 | |
4104 Node* phi_reg = NULL; | |
4105 uint phi_len = (uint)-1; | |
4106 if (phi_base != NULL && !phi_base->is_copy()) { | |
4107 // do not examine phi if degraded to a copy | |
4108 phi_reg = phi_base->region(); | |
4109 phi_len = phi_base->req(); | |
4110 // see if the phi is unfinished | |
4111 for (uint i = 1; i < phi_len; i++) { | |
4112 if (phi_base->in(i) == NULL) { | |
4113 // incomplete phi; do not look at it yet! | |
4114 phi_reg = NULL; | |
4115 phi_len = (uint)-1; | |
4116 break; | |
4117 } | |
4118 } | |
4119 } | |
4120 | |
4121 // Note: We do not call verify_sparse on entry, because inputs | |
4122 // can normalize to the base_memory via subsume_node or similar | |
4123 // mechanisms. This method repairs that damage. | |
4124 | |
4125 assert(!old_mbase || old_mbase->is_empty_memory(empty_mem), "consistent sentinels"); | |
4126 | |
4127 // Look at each slice. | |
4128 for (uint i = Compile::AliasIdxRaw; i < req(); i++) { | |
4129 Node* old_in = in(i); | |
4130 // calculate the old memory value | |
4131 Node* old_mem = old_in; | |
4132 if (old_mem == empty_mem) old_mem = old_base; | |
4133 assert(old_mem == memory_at(i), ""); | |
4134 | |
4135 // maybe update (reslice) the old memory value | |
4136 | |
4137 // simplify stacked MergeMems | |
4138 Node* new_mem = old_mem; | |
4139 MergeMemNode* old_mmem; | |
4140 if (old_mem != NULL && old_mem->is_MergeMem()) | |
4141 old_mmem = old_mem->as_MergeMem(); | |
4142 else | |
4143 old_mmem = NULL; | |
4144 if (old_mmem == this) { | |
4145 // This can happen if loops break up and safepoints disappear. | |
4146 // A merge of BotPtr (default) with a RawPtr memory derived from a | |
4147 // safepoint can be rewritten to a merge of the same BotPtr with | |
4148 // the BotPtr phi coming into the loop. If that phi disappears | |
4149 // also, we can end up with a self-loop of the mergemem. | |
4150 // In general, if loops degenerate and memory effects disappear, | |
4151 // a mergemem can be left looking at itself. This simply means | |
4152 // that the mergemem's default should be used, since there is | |
4153 // no longer any apparent effect on this slice. | |
4154 // Note: If a memory slice is a MergeMem cycle, it is unreachable | |
4155 // from start. Update the input to TOP. | |
4156 new_mem = (new_base == this || new_base == empty_mem)? empty_mem : new_base; | |
4157 } | |
4158 else if (old_mmem != NULL) { | |
4159 new_mem = old_mmem->memory_at(i); | |
4160 } | |
605 | 4161 // else preceding memory was not a MergeMem |
0 | 4162 |
4163 // replace equivalent phis (unfortunately, they do not GVN together) | |
4164 if (new_mem != NULL && new_mem != new_base && | |
4165 new_mem->req() == phi_len && new_mem->in(0) == phi_reg) { | |
4166 if (new_mem->is_Phi()) { | |
4167 PhiNode* phi_mem = new_mem->as_Phi(); | |
4168 for (uint i = 1; i < phi_len; i++) { | |
4169 if (phi_base->in(i) != phi_mem->in(i)) { | |
4170 phi_mem = NULL; | |
4171 break; | |
4172 } | |
4173 } | |
4174 if (phi_mem != NULL) { | |
4175 // equivalent phi nodes; revert to the def | |
4176 new_mem = new_base; | |
4177 } | |
4178 } | |
4179 } | |
4180 | |
4181 // maybe store down a new value | |
4182 Node* new_in = new_mem; | |
4183 if (new_in == new_base) new_in = empty_mem; | |
4184 | |
4185 if (new_in != old_in) { | |
4186 // Warning: Do not combine this "if" with the previous "if" | |
4187 // A memory slice might have be be rewritten even if it is semantically | |
4188 // unchanged, if the base_memory value has changed. | |
4189 set_req(i, new_in); | |
4190 progress = this; // Report progress | |
4191 } | |
4192 } | |
4193 | |
4194 if (new_base != old_base) { | |
4195 set_req(Compile::AliasIdxBot, new_base); | |
4196 // Don't use set_base_memory(new_base), because we need to update du. | |
4197 assert(base_memory() == new_base, ""); | |
4198 progress = this; | |
4199 } | |
4200 | |
4201 if( base_memory() == this ) { | |
4202 // a self cycle indicates this memory path is dead | |
4203 set_req(Compile::AliasIdxBot, empty_mem); | |
4204 } | |
4205 | |
4206 // Resolve external cycles by calling Ideal on a MergeMem base_memory | |
4207 // Recursion must occur after the self cycle check above | |
4208 if( base_memory()->is_MergeMem() ) { | |
4209 MergeMemNode *new_mbase = base_memory()->as_MergeMem(); | |
4210 Node *m = phase->transform(new_mbase); // Rollup any cycles | |
4211 if( m != NULL && (m->is_top() || | |
4212 m->is_MergeMem() && m->as_MergeMem()->base_memory() == empty_mem) ) { | |
4213 // propagate rollup of dead cycle to self | |
4214 set_req(Compile::AliasIdxBot, empty_mem); | |
4215 } | |
4216 } | |
4217 | |
4218 if( base_memory() == empty_mem ) { | |
4219 progress = this; | |
4220 // Cut inputs during Parse phase only. | |
4221 // During Optimize phase a dead MergeMem node will be subsumed by Top. | |
4222 if( !can_reshape ) { | |
4223 for (uint i = Compile::AliasIdxRaw; i < req(); i++) { | |
4224 if( in(i) != empty_mem ) { set_req(i, empty_mem); } | |
4225 } | |
4226 } | |
4227 } | |
4228 | |
4229 if( !progress && base_memory()->is_Phi() && can_reshape ) { | |
4230 // Check if PhiNode::Ideal's "Split phis through memory merges" | |
4231 // transform should be attempted. Look for this->phi->this cycle. | |
4232 uint merge_width = req(); | |
4233 if (merge_width > Compile::AliasIdxRaw) { | |
4234 PhiNode* phi = base_memory()->as_Phi(); | |
4235 for( uint i = 1; i < phi->req(); ++i ) {// For all paths in | |
4236 if (phi->in(i) == this) { | |
4237 phase->is_IterGVN()->_worklist.push(phi); | |
4238 break; | |
4239 } | |
4240 } | |
4241 } | |
4242 } | |
4243 | |
64
b8f5ba577b02
6673473: (Escape Analysis) Add the instance's field information to PhiNode
kvn
parents:
43
diff
changeset
|
4244 assert(progress || verify_sparse(), "please, no dups of base"); |
0 | 4245 return progress; |
4246 } | |
4247 | |
4248 //-------------------------set_base_memory------------------------------------- | |
4249 void MergeMemNode::set_base_memory(Node *new_base) { | |
4250 Node* empty_mem = empty_memory(); | |
4251 set_req(Compile::AliasIdxBot, new_base); | |
4252 assert(memory_at(req()) == new_base, "must set default memory"); | |
4253 // Clear out other occurrences of new_base: | |
4254 if (new_base != empty_mem) { | |
4255 for (uint i = Compile::AliasIdxRaw; i < req(); i++) { | |
4256 if (in(i) == new_base) set_req(i, empty_mem); | |
4257 } | |
4258 } | |
4259 } | |
4260 | |
4261 //------------------------------out_RegMask------------------------------------ | |
4262 const RegMask &MergeMemNode::out_RegMask() const { | |
4263 return RegMask::Empty; | |
4264 } | |
4265 | |
4266 //------------------------------dump_spec-------------------------------------- | |
4267 #ifndef PRODUCT | |
4268 void MergeMemNode::dump_spec(outputStream *st) const { | |
4269 st->print(" {"); | |
4270 Node* base_mem = base_memory(); | |
4271 for( uint i = Compile::AliasIdxRaw; i < req(); i++ ) { | |
4272 Node* mem = memory_at(i); | |
4273 if (mem == base_mem) { st->print(" -"); continue; } | |
4274 st->print( " N%d:", mem->_idx ); | |
4275 Compile::current()->get_adr_type(i)->dump_on(st); | |
4276 } | |
4277 st->print(" }"); | |
4278 } | |
4279 #endif // !PRODUCT | |
4280 | |
4281 | |
4282 #ifdef ASSERT | |
4283 static bool might_be_same(Node* a, Node* b) { | |
4284 if (a == b) return true; | |
4285 if (!(a->is_Phi() || b->is_Phi())) return false; | |
4286 // phis shift around during optimization | |
4287 return true; // pretty stupid... | |
4288 } | |
4289 | |
4290 // verify a narrow slice (either incoming or outgoing) | |
4291 static void verify_memory_slice(const MergeMemNode* m, int alias_idx, Node* n) { | |
4292 if (!VerifyAliases) return; // don't bother to verify unless requested | |
4293 if (is_error_reported()) return; // muzzle asserts when debugging an error | |
4294 if (Node::in_dump()) return; // muzzle asserts when printing | |
4295 assert(alias_idx >= Compile::AliasIdxRaw, "must not disturb base_memory or sentinel"); | |
4296 assert(n != NULL, ""); | |
4297 // Elide intervening MergeMem's | |
4298 while (n->is_MergeMem()) { | |
4299 n = n->as_MergeMem()->memory_at(alias_idx); | |
4300 } | |
4301 Compile* C = Compile::current(); | |
4302 const TypePtr* n_adr_type = n->adr_type(); | |
4303 if (n == m->empty_memory()) { | |
4304 // Implicit copy of base_memory() | |
4305 } else if (n_adr_type != TypePtr::BOTTOM) { | |
4306 assert(n_adr_type != NULL, "new memory must have a well-defined adr_type"); | |
4307 assert(C->must_alias(n_adr_type, alias_idx), "new memory must match selected slice"); | |
4308 } else { | |
4309 // A few places like make_runtime_call "know" that VM calls are narrow, | |
4310 // and can be used to update only the VM bits stored as TypeRawPtr::BOTTOM. | |
4311 bool expected_wide_mem = false; | |
4312 if (n == m->base_memory()) { | |
4313 expected_wide_mem = true; | |
4314 } else if (alias_idx == Compile::AliasIdxRaw || | |
4315 n == m->memory_at(Compile::AliasIdxRaw)) { | |
4316 expected_wide_mem = true; | |
4317 } else if (!C->alias_type(alias_idx)->is_rewritable()) { | |
4318 // memory can "leak through" calls on channels that | |
4319 // are write-once. Allow this also. | |
4320 expected_wide_mem = true; | |
4321 } | |
4322 assert(expected_wide_mem, "expected narrow slice replacement"); | |
4323 } | |
4324 } | |
4325 #else // !ASSERT | |
4326 #define verify_memory_slice(m,i,n) (0) // PRODUCT version is no-op | |
4327 #endif | |
4328 | |
4329 | |
4330 //-----------------------------memory_at--------------------------------------- | |
4331 Node* MergeMemNode::memory_at(uint alias_idx) const { | |
4332 assert(alias_idx >= Compile::AliasIdxRaw || | |
4333 alias_idx == Compile::AliasIdxBot && Compile::current()->AliasLevel() == 0, | |
4334 "must avoid base_memory and AliasIdxTop"); | |
4335 | |
4336 // Otherwise, it is a narrow slice. | |
4337 Node* n = alias_idx < req() ? in(alias_idx) : empty_memory(); | |
4338 Compile *C = Compile::current(); | |
4339 if (is_empty_memory(n)) { | |
4340 // the array is sparse; empty slots are the "top" node | |
4341 n = base_memory(); | |
4342 assert(Node::in_dump() | |
4343 || n == NULL || n->bottom_type() == Type::TOP | |
2317
5a41a201d08c
6812217: Base memory of MergeMem node violates assert during killing expanded AllocateArray node
kvn
parents:
2004
diff
changeset
|
4344 || n->adr_type() == NULL // address is TOP |
0 | 4345 || n->adr_type() == TypePtr::BOTTOM |
4346 || n->adr_type() == TypeRawPtr::BOTTOM | |
4347 || Compile::current()->AliasLevel() == 0, | |
4348 "must be a wide memory"); | |
4349 // AliasLevel == 0 if we are organizing the memory states manually. | |
4350 // See verify_memory_slice for comments on TypeRawPtr::BOTTOM. | |
4351 } else { | |
4352 // make sure the stored slice is sane | |
4353 #ifdef ASSERT | |
4354 if (is_error_reported() || Node::in_dump()) { | |
4355 } else if (might_be_same(n, base_memory())) { | |
4356 // Give it a pass: It is a mostly harmless repetition of the base. | |
4357 // This can arise normally from node subsumption during optimization. | |
4358 } else { | |
4359 verify_memory_slice(this, alias_idx, n); | |
4360 } | |
4361 #endif | |
4362 } | |
4363 return n; | |
4364 } | |
4365 | |
4366 //---------------------------set_memory_at------------------------------------- | |
4367 void MergeMemNode::set_memory_at(uint alias_idx, Node *n) { | |
4368 verify_memory_slice(this, alias_idx, n); | |
4369 Node* empty_mem = empty_memory(); | |
4370 if (n == base_memory()) n = empty_mem; // collapse default | |
4371 uint need_req = alias_idx+1; | |
4372 if (req() < need_req) { | |
4373 if (n == empty_mem) return; // already the default, so do not grow me | |
4374 // grow the sparse array | |
4375 do { | |
4376 add_req(empty_mem); | |
4377 } while (req() < need_req); | |
4378 } | |
4379 set_req( alias_idx, n ); | |
4380 } | |
4381 | |
4382 | |
4383 | |
4384 //--------------------------iteration_setup------------------------------------ | |
4385 void MergeMemNode::iteration_setup(const MergeMemNode* other) { | |
4386 if (other != NULL) { | |
4387 grow_to_match(other); | |
4388 // invariant: the finite support of mm2 is within mm->req() | |
4389 #ifdef ASSERT | |
4390 for (uint i = req(); i < other->req(); i++) { | |
4391 assert(other->is_empty_memory(other->in(i)), "slice left uncovered"); | |
4392 } | |
4393 #endif | |
4394 } | |
4395 // Replace spurious copies of base_memory by top. | |
4396 Node* base_mem = base_memory(); | |
4397 if (base_mem != NULL && !base_mem->is_top()) { | |
4398 for (uint i = Compile::AliasIdxBot+1, imax = req(); i < imax; i++) { | |
4399 if (in(i) == base_mem) | |
4400 set_req(i, empty_memory()); | |
4401 } | |
4402 } | |
4403 } | |
4404 | |
4405 //---------------------------grow_to_match------------------------------------- | |
4406 void MergeMemNode::grow_to_match(const MergeMemNode* other) { | |
4407 Node* empty_mem = empty_memory(); | |
4408 assert(other->is_empty_memory(empty_mem), "consistent sentinels"); | |
4409 // look for the finite support of the other memory | |
4410 for (uint i = other->req(); --i >= req(); ) { | |
4411 if (other->in(i) != empty_mem) { | |
4412 uint new_len = i+1; | |
4413 while (req() < new_len) add_req(empty_mem); | |
4414 break; | |
4415 } | |
4416 } | |
4417 } | |
4418 | |
4419 //---------------------------verify_sparse------------------------------------- | |
4420 #ifndef PRODUCT | |
4421 bool MergeMemNode::verify_sparse() const { | |
4422 assert(is_empty_memory(make_empty_memory()), "sane sentinel"); | |
4423 Node* base_mem = base_memory(); | |
4424 // The following can happen in degenerate cases, since empty==top. | |
4425 if (is_empty_memory(base_mem)) return true; | |
4426 for (uint i = Compile::AliasIdxRaw; i < req(); i++) { | |
4427 assert(in(i) != NULL, "sane slice"); | |
4428 if (in(i) == base_mem) return false; // should have been the sentinel value! | |
4429 } | |
4430 return true; | |
4431 } | |
4432 | |
4433 bool MergeMemStream::match_memory(Node* mem, const MergeMemNode* mm, int idx) { | |
4434 Node* n; | |
4435 n = mm->in(idx); | |
4436 if (mem == n) return true; // might be empty_memory() | |
4437 n = (idx == Compile::AliasIdxBot)? mm->base_memory(): mm->memory_at(idx); | |
4438 if (mem == n) return true; | |
4439 while (n->is_Phi() && (n = n->as_Phi()->is_copy()) != NULL) { | |
4440 if (mem == n) return true; | |
4441 if (n == NULL) break; | |
4442 } | |
4443 return false; | |
4444 } | |
4445 #endif // !PRODUCT |