Mercurial > hg > truffle
annotate src/share/vm/opto/graphKit.cpp @ 14649:f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | bb9356ec5967 |
children | 16c705d792be |
rev | line source |
---|---|
0 | 1 /* |
14223
de6a9e811145
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12966
diff
changeset
|
2 * Copyright (c) 2001, 2013, 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:
1397
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1397
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:
1397
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "compiler/compileLog.hpp" | |
27 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" | |
28 #include "gc_implementation/g1/heapRegion.hpp" | |
29 #include "gc_interface/collectedHeap.hpp" | |
30 #include "memory/barrierSet.hpp" | |
31 #include "memory/cardTableModRefBS.hpp" | |
32 #include "opto/addnode.hpp" | |
33 #include "opto/graphKit.hpp" | |
34 #include "opto/idealKit.hpp" | |
35 #include "opto/locknode.hpp" | |
36 #include "opto/machnode.hpp" | |
37 #include "opto/parse.hpp" | |
38 #include "opto/rootnode.hpp" | |
39 #include "opto/runtime.hpp" | |
40 #include "runtime/deoptimization.hpp" | |
41 #include "runtime/sharedRuntime.hpp" | |
0 | 42 |
43 //----------------------------GraphKit----------------------------------------- | |
44 // Main utility constructor. | |
45 GraphKit::GraphKit(JVMState* jvms) | |
46 : Phase(Phase::Parser), | |
47 _env(C->env()), | |
48 _gvn(*C->initial_gvn()) | |
49 { | |
50 _exceptions = jvms->map()->next_exception(); | |
51 if (_exceptions != NULL) jvms->map()->set_next_exception(NULL); | |
52 set_jvms(jvms); | |
53 } | |
54 | |
55 // Private constructor for parser. | |
56 GraphKit::GraphKit() | |
57 : Phase(Phase::Parser), | |
58 _env(C->env()), | |
59 _gvn(*C->initial_gvn()) | |
60 { | |
61 _exceptions = NULL; | |
62 set_map(NULL); | |
63 debug_only(_sp = -99); | |
64 debug_only(set_bci(-99)); | |
65 } | |
66 | |
67 | |
68 | |
69 //---------------------------clean_stack--------------------------------------- | |
70 // Clear away rubbish from the stack area of the JVM state. | |
71 // This destroys any arguments that may be waiting on the stack. | |
72 void GraphKit::clean_stack(int from_sp) { | |
73 SafePointNode* map = this->map(); | |
74 JVMState* jvms = this->jvms(); | |
75 int stk_size = jvms->stk_size(); | |
76 int stkoff = jvms->stkoff(); | |
77 Node* top = this->top(); | |
78 for (int i = from_sp; i < stk_size; i++) { | |
79 if (map->in(stkoff + i) != top) { | |
80 map->set_req(stkoff + i, top); | |
81 } | |
82 } | |
83 } | |
84 | |
85 | |
86 //--------------------------------sync_jvms----------------------------------- | |
87 // Make sure our current jvms agrees with our parse state. | |
88 JVMState* GraphKit::sync_jvms() const { | |
89 JVMState* jvms = this->jvms(); | |
90 jvms->set_bci(bci()); // Record the new bci in the JVMState | |
91 jvms->set_sp(sp()); // Record the new sp in the JVMState | |
92 assert(jvms_in_sync(), "jvms is now in sync"); | |
93 return jvms; | |
94 } | |
95 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
96 //--------------------------------sync_jvms_for_reexecute--------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
97 // Make sure our current jvms agrees with our parse state. This version |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
98 // uses the reexecute_sp for reexecuting bytecodes. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
99 JVMState* GraphKit::sync_jvms_for_reexecute() { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
100 JVMState* jvms = this->jvms(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
101 jvms->set_bci(bci()); // Record the new bci in the JVMState |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
102 jvms->set_sp(reexecute_sp()); // Record the new sp in the JVMState |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
103 return jvms; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
104 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
105 |
0 | 106 #ifdef ASSERT |
107 bool GraphKit::jvms_in_sync() const { | |
108 Parse* parse = is_Parse(); | |
109 if (parse == NULL) { | |
110 if (bci() != jvms()->bci()) return false; | |
111 if (sp() != (int)jvms()->sp()) return false; | |
112 return true; | |
113 } | |
114 if (jvms()->method() != parse->method()) return false; | |
115 if (jvms()->bci() != parse->bci()) return false; | |
116 int jvms_sp = jvms()->sp(); | |
117 if (jvms_sp != parse->sp()) return false; | |
118 int jvms_depth = jvms()->depth(); | |
119 if (jvms_depth != parse->depth()) return false; | |
120 return true; | |
121 } | |
122 | |
123 // Local helper checks for special internal merge points | |
124 // used to accumulate and merge exception states. | |
125 // They are marked by the region's in(0) edge being the map itself. | |
126 // Such merge points must never "escape" into the parser at large, | |
127 // until they have been handed to gvn.transform. | |
128 static bool is_hidden_merge(Node* reg) { | |
129 if (reg == NULL) return false; | |
130 if (reg->is_Phi()) { | |
131 reg = reg->in(0); | |
132 if (reg == NULL) return false; | |
133 } | |
134 return reg->is_Region() && reg->in(0) != NULL && reg->in(0)->is_Root(); | |
135 } | |
136 | |
137 void GraphKit::verify_map() const { | |
138 if (map() == NULL) return; // null map is OK | |
139 assert(map()->req() <= jvms()->endoff(), "no extra garbage on map"); | |
140 assert(!map()->has_exceptions(), "call add_exception_states_from 1st"); | |
141 assert(!is_hidden_merge(control()), "call use_exception_state, not set_map"); | |
142 } | |
143 | |
144 void GraphKit::verify_exception_state(SafePointNode* ex_map) { | |
145 assert(ex_map->next_exception() == NULL, "not already part of a chain"); | |
146 assert(has_saved_ex_oop(ex_map), "every exception state has an ex_oop"); | |
147 } | |
148 #endif | |
149 | |
150 //---------------------------stop_and_kill_map--------------------------------- | |
151 // Set _map to NULL, signalling a stop to further bytecode execution. | |
152 // First smash the current map's control to a constant, to mark it dead. | |
153 void GraphKit::stop_and_kill_map() { | |
154 SafePointNode* dead_map = stop(); | |
155 if (dead_map != NULL) { | |
7196
2aff40cb4703
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
7194
diff
changeset
|
156 dead_map->disconnect_inputs(NULL, C); // Mark the map as killed. |
0 | 157 assert(dead_map->is_killed(), "must be so marked"); |
158 } | |
159 } | |
160 | |
161 | |
162 //--------------------------------stopped-------------------------------------- | |
163 // Tell if _map is NULL, or control is top. | |
164 bool GraphKit::stopped() { | |
165 if (map() == NULL) return true; | |
166 else if (control() == top()) return true; | |
167 else return false; | |
168 } | |
169 | |
170 | |
171 //-----------------------------has_ex_handler---------------------------------- | |
172 // Tell if this method or any caller method has exception handlers. | |
173 bool GraphKit::has_ex_handler() { | |
174 for (JVMState* jvmsp = jvms(); jvmsp != NULL; jvmsp = jvmsp->caller()) { | |
175 if (jvmsp->has_method() && jvmsp->method()->has_exception_handlers()) { | |
176 return true; | |
177 } | |
178 } | |
179 return false; | |
180 } | |
181 | |
182 //------------------------------save_ex_oop------------------------------------ | |
183 // Save an exception without blowing stack contents or other JVM state. | |
184 void GraphKit::set_saved_ex_oop(SafePointNode* ex_map, Node* ex_oop) { | |
185 assert(!has_saved_ex_oop(ex_map), "clear ex-oop before setting again"); | |
186 ex_map->add_req(ex_oop); | |
187 debug_only(verify_exception_state(ex_map)); | |
188 } | |
189 | |
190 inline static Node* common_saved_ex_oop(SafePointNode* ex_map, bool clear_it) { | |
191 assert(GraphKit::has_saved_ex_oop(ex_map), "ex_oop must be there"); | |
192 Node* ex_oop = ex_map->in(ex_map->req()-1); | |
193 if (clear_it) ex_map->del_req(ex_map->req()-1); | |
194 return ex_oop; | |
195 } | |
196 | |
197 //-----------------------------saved_ex_oop------------------------------------ | |
198 // Recover a saved exception from its map. | |
199 Node* GraphKit::saved_ex_oop(SafePointNode* ex_map) { | |
200 return common_saved_ex_oop(ex_map, false); | |
201 } | |
202 | |
203 //--------------------------clear_saved_ex_oop--------------------------------- | |
204 // Erase a previously saved exception from its map. | |
205 Node* GraphKit::clear_saved_ex_oop(SafePointNode* ex_map) { | |
206 return common_saved_ex_oop(ex_map, true); | |
207 } | |
208 | |
209 #ifdef ASSERT | |
210 //---------------------------has_saved_ex_oop---------------------------------- | |
211 // Erase a previously saved exception from its map. | |
212 bool GraphKit::has_saved_ex_oop(SafePointNode* ex_map) { | |
213 return ex_map->req() == ex_map->jvms()->endoff()+1; | |
214 } | |
215 #endif | |
216 | |
217 //-------------------------make_exception_state-------------------------------- | |
218 // Turn the current JVM state into an exception state, appending the ex_oop. | |
219 SafePointNode* GraphKit::make_exception_state(Node* ex_oop) { | |
220 sync_jvms(); | |
221 SafePointNode* ex_map = stop(); // do not manipulate this map any more | |
222 set_saved_ex_oop(ex_map, ex_oop); | |
223 return ex_map; | |
224 } | |
225 | |
226 | |
227 //--------------------------add_exception_state-------------------------------- | |
228 // Add an exception to my list of exceptions. | |
229 void GraphKit::add_exception_state(SafePointNode* ex_map) { | |
230 if (ex_map == NULL || ex_map->control() == top()) { | |
231 return; | |
232 } | |
233 #ifdef ASSERT | |
234 verify_exception_state(ex_map); | |
235 if (has_exceptions()) { | |
236 assert(ex_map->jvms()->same_calls_as(_exceptions->jvms()), "all collected exceptions must come from the same place"); | |
237 } | |
238 #endif | |
239 | |
240 // If there is already an exception of exactly this type, merge with it. | |
241 // In particular, null-checks and other low-level exceptions common up here. | |
242 Node* ex_oop = saved_ex_oop(ex_map); | |
243 const Type* ex_type = _gvn.type(ex_oop); | |
244 if (ex_oop == top()) { | |
245 // No action needed. | |
246 return; | |
247 } | |
248 assert(ex_type->isa_instptr(), "exception must be an instance"); | |
249 for (SafePointNode* e2 = _exceptions; e2 != NULL; e2 = e2->next_exception()) { | |
250 const Type* ex_type2 = _gvn.type(saved_ex_oop(e2)); | |
251 // We check sp also because call bytecodes can generate exceptions | |
252 // both before and after arguments are popped! | |
253 if (ex_type2 == ex_type | |
254 && e2->_jvms->sp() == ex_map->_jvms->sp()) { | |
255 combine_exception_states(ex_map, e2); | |
256 return; | |
257 } | |
258 } | |
259 | |
260 // No pre-existing exception of the same type. Chain it on the list. | |
261 push_exception_state(ex_map); | |
262 } | |
263 | |
264 //-----------------------add_exception_states_from----------------------------- | |
265 void GraphKit::add_exception_states_from(JVMState* jvms) { | |
266 SafePointNode* ex_map = jvms->map()->next_exception(); | |
267 if (ex_map != NULL) { | |
268 jvms->map()->set_next_exception(NULL); | |
269 for (SafePointNode* next_map; ex_map != NULL; ex_map = next_map) { | |
270 next_map = ex_map->next_exception(); | |
271 ex_map->set_next_exception(NULL); | |
272 add_exception_state(ex_map); | |
273 } | |
274 } | |
275 } | |
276 | |
277 //-----------------------transfer_exceptions_into_jvms------------------------- | |
278 JVMState* GraphKit::transfer_exceptions_into_jvms() { | |
279 if (map() == NULL) { | |
280 // We need a JVMS to carry the exceptions, but the map has gone away. | |
281 // Create a scratch JVMS, cloned from any of the exception states... | |
282 if (has_exceptions()) { | |
283 _map = _exceptions; | |
284 _map = clone_map(); | |
285 _map->set_next_exception(NULL); | |
286 clear_saved_ex_oop(_map); | |
287 debug_only(verify_map()); | |
288 } else { | |
289 // ...or created from scratch | |
290 JVMState* jvms = new (C) JVMState(_method, NULL); | |
291 jvms->set_bci(_bci); | |
292 jvms->set_sp(_sp); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
293 jvms->set_map(new (C) SafePointNode(TypeFunc::Parms, jvms)); |
0 | 294 set_jvms(jvms); |
295 for (uint i = 0; i < map()->req(); i++) map()->init_req(i, top()); | |
296 set_all_memory(top()); | |
297 while (map()->req() < jvms->endoff()) map()->add_req(top()); | |
298 } | |
299 // (This is a kludge, in case you didn't notice.) | |
300 set_control(top()); | |
301 } | |
302 JVMState* jvms = sync_jvms(); | |
303 assert(!jvms->map()->has_exceptions(), "no exceptions on this map yet"); | |
304 jvms->map()->set_next_exception(_exceptions); | |
305 _exceptions = NULL; // done with this set of exceptions | |
306 return jvms; | |
307 } | |
308 | |
309 static inline void add_n_reqs(Node* dstphi, Node* srcphi) { | |
310 assert(is_hidden_merge(dstphi), "must be a special merge node"); | |
311 assert(is_hidden_merge(srcphi), "must be a special merge node"); | |
312 uint limit = srcphi->req(); | |
313 for (uint i = PhiNode::Input; i < limit; i++) { | |
314 dstphi->add_req(srcphi->in(i)); | |
315 } | |
316 } | |
317 static inline void add_one_req(Node* dstphi, Node* src) { | |
318 assert(is_hidden_merge(dstphi), "must be a special merge node"); | |
319 assert(!is_hidden_merge(src), "must not be a special merge node"); | |
320 dstphi->add_req(src); | |
321 } | |
322 | |
323 //-----------------------combine_exception_states------------------------------ | |
324 // This helper function combines exception states by building phis on a | |
325 // specially marked state-merging region. These regions and phis are | |
326 // untransformed, and can build up gradually. The region is marked by | |
327 // having a control input of its exception map, rather than NULL. Such | |
328 // regions do not appear except in this function, and in use_exception_state. | |
329 void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* phi_map) { | |
330 if (failing()) return; // dying anyway... | |
331 JVMState* ex_jvms = ex_map->_jvms; | |
332 assert(ex_jvms->same_calls_as(phi_map->_jvms), "consistent call chains"); | |
333 assert(ex_jvms->stkoff() == phi_map->_jvms->stkoff(), "matching locals"); | |
334 assert(ex_jvms->sp() == phi_map->_jvms->sp(), "matching stack sizes"); | |
335 assert(ex_jvms->monoff() == phi_map->_jvms->monoff(), "matching JVMS"); | |
10278 | 336 assert(ex_jvms->scloff() == phi_map->_jvms->scloff(), "matching scalar replaced objects"); |
0 | 337 assert(ex_map->req() == phi_map->req(), "matching maps"); |
338 uint tos = ex_jvms->stkoff() + ex_jvms->sp(); | |
339 Node* hidden_merge_mark = root(); | |
340 Node* region = phi_map->control(); | |
341 MergeMemNode* phi_mem = phi_map->merged_memory(); | |
342 MergeMemNode* ex_mem = ex_map->merged_memory(); | |
343 if (region->in(0) != hidden_merge_mark) { | |
344 // The control input is not (yet) a specially-marked region in phi_map. | |
345 // Make it so, and build some phis. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
346 region = new (C) RegionNode(2); |
0 | 347 _gvn.set_type(region, Type::CONTROL); |
348 region->set_req(0, hidden_merge_mark); // marks an internal ex-state | |
349 region->init_req(1, phi_map->control()); | |
350 phi_map->set_control(region); | |
351 Node* io_phi = PhiNode::make(region, phi_map->i_o(), Type::ABIO); | |
352 record_for_igvn(io_phi); | |
353 _gvn.set_type(io_phi, Type::ABIO); | |
354 phi_map->set_i_o(io_phi); | |
355 for (MergeMemStream mms(phi_mem); mms.next_non_empty(); ) { | |
356 Node* m = mms.memory(); | |
357 Node* m_phi = PhiNode::make(region, m, Type::MEMORY, mms.adr_type(C)); | |
358 record_for_igvn(m_phi); | |
359 _gvn.set_type(m_phi, Type::MEMORY); | |
360 mms.set_memory(m_phi); | |
361 } | |
362 } | |
363 | |
364 // Either or both of phi_map and ex_map might already be converted into phis. | |
365 Node* ex_control = ex_map->control(); | |
366 // if there is special marking on ex_map also, we add multiple edges from src | |
367 bool add_multiple = (ex_control->in(0) == hidden_merge_mark); | |
368 // how wide was the destination phi_map, originally? | |
369 uint orig_width = region->req(); | |
370 | |
371 if (add_multiple) { | |
372 add_n_reqs(region, ex_control); | |
373 add_n_reqs(phi_map->i_o(), ex_map->i_o()); | |
374 } else { | |
375 // ex_map has no merges, so we just add single edges everywhere | |
376 add_one_req(region, ex_control); | |
377 add_one_req(phi_map->i_o(), ex_map->i_o()); | |
378 } | |
379 for (MergeMemStream mms(phi_mem, ex_mem); mms.next_non_empty2(); ) { | |
380 if (mms.is_empty()) { | |
381 // get a copy of the base memory, and patch some inputs into it | |
382 const TypePtr* adr_type = mms.adr_type(C); | |
383 Node* phi = mms.force_memory()->as_Phi()->slice_memory(adr_type); | |
384 assert(phi->as_Phi()->region() == mms.base_memory()->in(0), ""); | |
385 mms.set_memory(phi); | |
386 // Prepare to append interesting stuff onto the newly sliced phi: | |
387 while (phi->req() > orig_width) phi->del_req(phi->req()-1); | |
388 } | |
389 // Append stuff from ex_map: | |
390 if (add_multiple) { | |
391 add_n_reqs(mms.memory(), mms.memory2()); | |
392 } else { | |
393 add_one_req(mms.memory(), mms.memory2()); | |
394 } | |
395 } | |
396 uint limit = ex_map->req(); | |
397 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
398 // Skip everything in the JVMS after tos. (The ex_oop follows.) | |
399 if (i == tos) i = ex_jvms->monoff(); | |
400 Node* src = ex_map->in(i); | |
401 Node* dst = phi_map->in(i); | |
402 if (src != dst) { | |
403 PhiNode* phi; | |
404 if (dst->in(0) != region) { | |
405 dst = phi = PhiNode::make(region, dst, _gvn.type(dst)); | |
406 record_for_igvn(phi); | |
407 _gvn.set_type(phi, phi->type()); | |
408 phi_map->set_req(i, dst); | |
409 // Prepare to append interesting stuff onto the new phi: | |
410 while (dst->req() > orig_width) dst->del_req(dst->req()-1); | |
411 } else { | |
412 assert(dst->is_Phi(), "nobody else uses a hidden region"); | |
10278 | 413 phi = dst->as_Phi(); |
0 | 414 } |
415 if (add_multiple && src->in(0) == ex_control) { | |
416 // Both are phis. | |
417 add_n_reqs(dst, src); | |
418 } else { | |
419 while (dst->req() < region->req()) add_one_req(dst, src); | |
420 } | |
421 const Type* srctype = _gvn.type(src); | |
422 if (phi->type() != srctype) { | |
14383
5ec7dace41a6
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
14223
diff
changeset
|
423 const Type* dsttype = phi->type()->meet_speculative(srctype); |
0 | 424 if (phi->type() != dsttype) { |
425 phi->set_type(dsttype); | |
426 _gvn.set_type(phi, dsttype); | |
427 } | |
428 } | |
429 } | |
430 } | |
431 } | |
432 | |
433 //--------------------------use_exception_state-------------------------------- | |
434 Node* GraphKit::use_exception_state(SafePointNode* phi_map) { | |
435 if (failing()) { stop(); return top(); } | |
436 Node* region = phi_map->control(); | |
437 Node* hidden_merge_mark = root(); | |
438 assert(phi_map->jvms()->map() == phi_map, "sanity: 1-1 relation"); | |
439 Node* ex_oop = clear_saved_ex_oop(phi_map); | |
440 if (region->in(0) == hidden_merge_mark) { | |
441 // Special marking for internal ex-states. Process the phis now. | |
442 region->set_req(0, region); // now it's an ordinary region | |
443 set_jvms(phi_map->jvms()); // ...so now we can use it as a map | |
444 // Note: Setting the jvms also sets the bci and sp. | |
445 set_control(_gvn.transform(region)); | |
446 uint tos = jvms()->stkoff() + sp(); | |
447 for (uint i = 1; i < tos; i++) { | |
448 Node* x = phi_map->in(i); | |
449 if (x->in(0) == region) { | |
450 assert(x->is_Phi(), "expected a special phi"); | |
451 phi_map->set_req(i, _gvn.transform(x)); | |
452 } | |
453 } | |
454 for (MergeMemStream mms(merged_memory()); mms.next_non_empty(); ) { | |
455 Node* x = mms.memory(); | |
456 if (x->in(0) == region) { | |
457 assert(x->is_Phi(), "nobody else uses a hidden region"); | |
458 mms.set_memory(_gvn.transform(x)); | |
459 } | |
460 } | |
461 if (ex_oop->in(0) == region) { | |
462 assert(ex_oop->is_Phi(), "expected a special phi"); | |
463 ex_oop = _gvn.transform(ex_oop); | |
464 } | |
465 } else { | |
466 set_jvms(phi_map->jvms()); | |
467 } | |
468 | |
469 assert(!is_hidden_merge(phi_map->control()), "hidden ex. states cleared"); | |
470 assert(!is_hidden_merge(phi_map->i_o()), "hidden ex. states cleared"); | |
471 return ex_oop; | |
472 } | |
473 | |
474 //---------------------------------java_bc------------------------------------- | |
475 Bytecodes::Code GraphKit::java_bc() const { | |
476 ciMethod* method = this->method(); | |
477 int bci = this->bci(); | |
478 if (method != NULL && bci != InvocationEntryBci) | |
479 return method->java_code_at_bci(bci); | |
480 else | |
481 return Bytecodes::_illegal; | |
482 } | |
483 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
484 void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptReason reason, |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
485 bool must_throw) { |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
486 // if the exception capability is set, then we will generate code |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
487 // to check the JavaThread.should_post_on_exceptions flag to see |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
488 // if we actually need to report exception events (for this |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
489 // thread). If we don't need to report exception events, we will |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
490 // take the normal fast path provided by add_exception_events. If |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
491 // exception event reporting is enabled for this thread, we will |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
492 // take the uncommon_trap in the BuildCutout below. |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
493 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
494 // first must access the should_post_on_exceptions_flag in this thread's JavaThread |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
495 Node* jthread = _gvn.transform(new (C) ThreadLocalNode()); |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
496 Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
497 Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered); |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
498 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
499 // Test the should_post_on_exceptions_flag vs. 0 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
500 Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
501 Node* tst = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) ); |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
502 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
503 // Branch to slow_path if should_post_on_exceptions_flag was true |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
504 { BuildCutout unless(this, tst, PROB_MAX); |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
505 // Do not try anything fancy if we're notifying the VM on every throw. |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
506 // Cf. case Bytecodes::_athrow in parse2.cpp. |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
507 uncommon_trap(reason, Deoptimization::Action_none, |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
508 (ciKlass*)NULL, (char*)NULL, must_throw); |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
509 } |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
510 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
511 } |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
512 |
0 | 513 //------------------------------builtin_throw---------------------------------- |
514 void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) { | |
515 bool must_throw = true; | |
516 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
517 if (env()->jvmti_can_post_on_exceptions()) { |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
518 // check if we must post exception events, take uncommon trap if so |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
519 uncommon_trap_if_should_post_on_exceptions(reason, must_throw); |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
520 // here if should_post_on_exceptions is false |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
521 // continue on with the normal codegen |
0 | 522 } |
523 | |
524 // If this particular condition has not yet happened at this | |
525 // bytecode, then use the uncommon trap mechanism, and allow for | |
526 // a future recompilation if several traps occur here. | |
527 // If the throw is hot, try to use a more complicated inline mechanism | |
528 // which keeps execution inside the compiled code. | |
529 bool treat_throw_as_hot = false; | |
530 ciMethodData* md = method()->method_data(); | |
531 | |
532 if (ProfileTraps) { | |
533 if (too_many_traps(reason)) { | |
534 treat_throw_as_hot = true; | |
535 } | |
536 // (If there is no MDO at all, assume it is early in | |
537 // execution, and that any deopts are part of the | |
538 // startup transient, and don't need to be remembered.) | |
539 | |
540 // Also, if there is a local exception handler, treat all throws | |
541 // as hot if there has been at least one in this method. | |
542 if (C->trap_count(reason) != 0 | |
543 && method()->method_data()->trap_count(reason) != 0 | |
544 && has_ex_handler()) { | |
545 treat_throw_as_hot = true; | |
546 } | |
547 } | |
548 | |
549 // If this throw happens frequently, an uncommon trap might cause | |
550 // a performance pothole. If there is a local exception handler, | |
551 // and if this particular bytecode appears to be deoptimizing often, | |
552 // let us handle the throw inline, with a preconstructed instance. | |
553 // Note: If the deopt count has blown up, the uncommon trap | |
554 // runtime is going to flush this nmethod, not matter what. | |
555 if (treat_throw_as_hot | |
556 && (!StackTraceInThrowable || OmitStackTraceInFastThrow)) { | |
557 // If the throw is local, we use a pre-existing instance and | |
558 // punt on the backtrace. This would lead to a missing backtrace | |
559 // (a repeat of 4292742) if the backtrace object is ever asked | |
560 // for its backtrace. | |
561 // Fixing this remaining case of 4292742 requires some flavor of | |
562 // escape analysis. Leave that for the future. | |
563 ciInstance* ex_obj = NULL; | |
564 switch (reason) { | |
565 case Deoptimization::Reason_null_check: | |
566 ex_obj = env()->NullPointerException_instance(); | |
567 break; | |
568 case Deoptimization::Reason_div0_check: | |
569 ex_obj = env()->ArithmeticException_instance(); | |
570 break; | |
571 case Deoptimization::Reason_range_check: | |
572 ex_obj = env()->ArrayIndexOutOfBoundsException_instance(); | |
573 break; | |
574 case Deoptimization::Reason_class_check: | |
575 if (java_bc() == Bytecodes::_aastore) { | |
576 ex_obj = env()->ArrayStoreException_instance(); | |
577 } else { | |
578 ex_obj = env()->ClassCastException_instance(); | |
579 } | |
580 break; | |
581 } | |
582 if (failing()) { stop(); return; } // exception allocation might fail | |
583 if (ex_obj != NULL) { | |
584 // Cheat with a preallocated exception object. | |
585 if (C->log() != NULL) | |
586 C->log()->elem("hot_throw preallocated='1' reason='%s'", | |
587 Deoptimization::trap_reason_name(reason)); | |
588 const TypeInstPtr* ex_con = TypeInstPtr::make(ex_obj); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
113
diff
changeset
|
589 Node* ex_node = _gvn.transform( ConNode::make(C, ex_con) ); |
0 | 590 |
591 // Clear the detail message of the preallocated exception object. | |
592 // Weblogic sometimes mutates the detail message of exceptions | |
593 // using reflection. | |
594 int offset = java_lang_Throwable::get_detailMessage_offset(); | |
595 const TypePtr* adr_typ = ex_con->add_offset(offset); | |
596 | |
597 Node *adr = basic_plus_adr(ex_node, ex_node, offset); | |
1965
f264f4c42799
7000491: assert(false) failed: should be optimized out in SharedRuntime::g1_wb_pre
kvn
parents:
1786
diff
changeset
|
598 const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
599 // Conservatively release stores of object references. |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
600 Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, MemNode::release); |
0 | 601 |
602 add_exception_state(make_exception_state(ex_node)); | |
603 return; | |
604 } | |
605 } | |
606 | |
607 // %%% Maybe add entry to OptoRuntime which directly throws the exc.? | |
608 // It won't be much cheaper than bailing to the interp., since we'll | |
609 // have to pass up all the debug-info, and the runtime will have to | |
610 // create the stack trace. | |
611 | |
612 // Usual case: Bail to interpreter. | |
613 // Reserve the right to recompile if we haven't seen anything yet. | |
614 | |
615 Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; | |
616 if (treat_throw_as_hot | |
617 && (method()->method_data()->trap_recompiled_at(bci()) | |
618 || C->too_many_traps(reason))) { | |
619 // We cannot afford to take more traps here. Suffer in the interpreter. | |
620 if (C->log() != NULL) | |
621 C->log()->elem("hot_throw preallocated='0' reason='%s' mcount='%d'", | |
622 Deoptimization::trap_reason_name(reason), | |
623 C->trap_count(reason)); | |
624 action = Deoptimization::Action_none; | |
625 } | |
626 | |
627 // "must_throw" prunes the JVM state to include only the stack, if there | |
628 // are no local exception handlers. This should cut down on register | |
629 // allocation time and code size, by drastically reducing the number | |
630 // of in-edges on the call to the uncommon trap. | |
631 | |
632 uncommon_trap(reason, action, (ciKlass*)NULL, (char*)NULL, must_throw); | |
633 } | |
634 | |
635 | |
636 //----------------------------PreserveJVMState--------------------------------- | |
637 PreserveJVMState::PreserveJVMState(GraphKit* kit, bool clone_map) { | |
638 debug_only(kit->verify_map()); | |
639 _kit = kit; | |
640 _map = kit->map(); // preserve the map | |
641 _sp = kit->sp(); | |
642 kit->set_map(clone_map ? kit->clone_map() : NULL); | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
643 Compile::current()->inc_preserve_jvm_state(); |
0 | 644 #ifdef ASSERT |
645 _bci = kit->bci(); | |
646 Parse* parser = kit->is_Parse(); | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
366
diff
changeset
|
647 int block = (parser == NULL || parser->block() == NULL) ? -1 : parser->block()->rpo(); |
0 | 648 _block = block; |
649 #endif | |
650 } | |
651 PreserveJVMState::~PreserveJVMState() { | |
652 GraphKit* kit = _kit; | |
653 #ifdef ASSERT | |
654 assert(kit->bci() == _bci, "bci must not shift"); | |
655 Parse* parser = kit->is_Parse(); | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
366
diff
changeset
|
656 int block = (parser == NULL || parser->block() == NULL) ? -1 : parser->block()->rpo(); |
0 | 657 assert(block == _block, "block must not shift"); |
658 #endif | |
659 kit->set_map(_map); | |
660 kit->set_sp(_sp); | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
661 Compile::current()->dec_preserve_jvm_state(); |
0 | 662 } |
663 | |
664 | |
665 //-----------------------------BuildCutout------------------------------------- | |
666 BuildCutout::BuildCutout(GraphKit* kit, Node* p, float prob, float cnt) | |
667 : PreserveJVMState(kit) | |
668 { | |
669 assert(p->is_Con() || p->is_Bool(), "test must be a bool"); | |
670 SafePointNode* outer_map = _map; // preserved map is caller's | |
671 SafePointNode* inner_map = kit->map(); | |
672 IfNode* iff = kit->create_and_map_if(outer_map->control(), p, prob, cnt); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
673 outer_map->set_control(kit->gvn().transform( new (kit->C) IfTrueNode(iff) )); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
674 inner_map->set_control(kit->gvn().transform( new (kit->C) IfFalseNode(iff) )); |
0 | 675 } |
676 BuildCutout::~BuildCutout() { | |
677 GraphKit* kit = _kit; | |
678 assert(kit->stopped(), "cutout code must stop, throw, return, etc."); | |
679 } | |
680 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
681 //---------------------------PreserveReexecuteState---------------------------- |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
682 PreserveReexecuteState::PreserveReexecuteState(GraphKit* kit) { |
950
8fe1963e3964
6875577: CTW fails with /hotspot/src/share/vm/opto/memnode.cpp
kvn
parents:
900
diff
changeset
|
683 assert(!kit->stopped(), "must call stopped() before"); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
684 _kit = kit; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
685 _sp = kit->sp(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
686 _reexecute = kit->jvms()->_reexecute; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
687 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
688 PreserveReexecuteState::~PreserveReexecuteState() { |
950
8fe1963e3964
6875577: CTW fails with /hotspot/src/share/vm/opto/memnode.cpp
kvn
parents:
900
diff
changeset
|
689 if (_kit->stopped()) return; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
690 _kit->jvms()->_reexecute = _reexecute; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
691 _kit->set_sp(_sp); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
692 } |
0 | 693 |
694 //------------------------------clone_map-------------------------------------- | |
695 // Implementation of PreserveJVMState | |
696 // | |
697 // Only clone_map(...) here. If this function is only used in the | |
698 // PreserveJVMState class we may want to get rid of this extra | |
699 // function eventually and do it all there. | |
700 | |
701 SafePointNode* GraphKit::clone_map() { | |
702 if (map() == NULL) return NULL; | |
703 | |
704 // Clone the memory edge first | |
705 Node* mem = MergeMemNode::make(C, map()->memory()); | |
706 gvn().set_type_bottom(mem); | |
707 | |
708 SafePointNode *clonemap = (SafePointNode*)map()->clone(); | |
709 JVMState* jvms = this->jvms(); | |
710 JVMState* clonejvms = jvms->clone_shallow(C); | |
711 clonemap->set_memory(mem); | |
712 clonemap->set_jvms(clonejvms); | |
713 clonejvms->set_map(clonemap); | |
714 record_for_igvn(clonemap); | |
715 gvn().set_type_bottom(clonemap); | |
716 return clonemap; | |
717 } | |
718 | |
719 | |
720 //-----------------------------set_map_clone----------------------------------- | |
721 void GraphKit::set_map_clone(SafePointNode* m) { | |
722 _map = m; | |
723 _map = clone_map(); | |
724 _map->set_next_exception(NULL); | |
725 debug_only(verify_map()); | |
726 } | |
727 | |
728 | |
729 //----------------------------kill_dead_locals--------------------------------- | |
730 // Detect any locals which are known to be dead, and force them to top. | |
731 void GraphKit::kill_dead_locals() { | |
732 // Consult the liveness information for the locals. If any | |
733 // of them are unused, then they can be replaced by top(). This | |
734 // should help register allocation time and cut down on the size | |
735 // of the deoptimization information. | |
736 | |
737 // This call is made from many of the bytecode handling | |
738 // subroutines called from the Big Switch in do_one_bytecode. | |
739 // Every bytecode which might include a slow path is responsible | |
740 // for killing its dead locals. The more consistent we | |
741 // are about killing deads, the fewer useless phis will be | |
742 // constructed for them at various merge points. | |
743 | |
744 // bci can be -1 (InvocationEntryBci). We return the entry | |
745 // liveness for the method. | |
746 | |
747 if (method() == NULL || method()->code_size() == 0) { | |
748 // We are building a graph for a call to a native method. | |
749 // All locals are live. | |
750 return; | |
751 } | |
752 | |
753 ResourceMark rm; | |
754 | |
755 // Consult the liveness information for the locals. If any | |
756 // of them are unused, then they can be replaced by top(). This | |
757 // should help register allocation time and cut down on the size | |
758 // of the deoptimization information. | |
759 MethodLivenessResult live_locals = method()->liveness_at_bci(bci()); | |
760 | |
761 int len = (int)live_locals.size(); | |
762 assert(len <= jvms()->loc_size(), "too many live locals"); | |
763 for (int local = 0; local < len; local++) { | |
764 if (!live_locals.at(local)) { | |
765 set_local(local, top()); | |
766 } | |
767 } | |
768 } | |
769 | |
770 #ifdef ASSERT | |
771 //-------------------------dead_locals_are_killed------------------------------ | |
772 // Return true if all dead locals are set to top in the map. | |
773 // Used to assert "clean" debug info at various points. | |
774 bool GraphKit::dead_locals_are_killed() { | |
775 if (method() == NULL || method()->code_size() == 0) { | |
776 // No locals need to be dead, so all is as it should be. | |
777 return true; | |
778 } | |
779 | |
780 // Make sure somebody called kill_dead_locals upstream. | |
781 ResourceMark rm; | |
782 for (JVMState* jvms = this->jvms(); jvms != NULL; jvms = jvms->caller()) { | |
783 if (jvms->loc_size() == 0) continue; // no locals to consult | |
784 SafePointNode* map = jvms->map(); | |
785 ciMethod* method = jvms->method(); | |
786 int bci = jvms->bci(); | |
787 if (jvms == this->jvms()) { | |
788 bci = this->bci(); // it might not yet be synched | |
789 } | |
790 MethodLivenessResult live_locals = method->liveness_at_bci(bci); | |
791 int len = (int)live_locals.size(); | |
792 if (!live_locals.is_valid() || len == 0) | |
793 // This method is trivial, or is poisoned by a breakpoint. | |
794 return true; | |
795 assert(len == jvms->loc_size(), "live map consistent with locals map"); | |
796 for (int local = 0; local < len; local++) { | |
797 if (!live_locals.at(local) && map->local(jvms, local) != top()) { | |
798 if (PrintMiscellaneous && (Verbose || WizardMode)) { | |
799 tty->print_cr("Zombie local %d: ", local); | |
800 jvms->dump(); | |
801 } | |
802 return false; | |
803 } | |
804 } | |
805 } | |
806 return true; | |
807 } | |
808 | |
809 #endif //ASSERT | |
810 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
811 // Helper function for enforcing certain bytecodes to reexecute if |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
812 // deoptimization happens |
1252
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
813 static bool should_reexecute_implied_by_bytecode(JVMState *jvms, bool is_anewarray) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
814 ciMethod* cur_method = jvms->method(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
815 int cur_bci = jvms->bci(); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
816 if (cur_method != NULL && cur_bci != InvocationEntryBci) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
817 Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci); |
1252
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
818 return Interpreter::bytecode_should_reexecute(code) || |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
819 is_anewarray && code == Bytecodes::_multianewarray; |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
820 // Reexecute _multianewarray bytecode which was replaced with |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
821 // sequence of [a]newarray. See Parse::do_multianewarray(). |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
822 // |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
823 // Note: interpreter should not have it set since this optimization |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
824 // is limited by dimensions and guarded by flag so in some cases |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
825 // multianewarray() runtime calls will be generated and |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
826 // the bytecode should not be reexecutes (stack will not be reset). |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
827 } else |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
828 return false; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
829 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
830 |
0 | 831 // Helper function for adding JVMState and debug information to node |
832 void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { | |
833 // Add the safepoint edges to the call (or other safepoint). | |
834 | |
835 // Make sure dead locals are set to top. This | |
836 // should help register allocation time and cut down on the size | |
837 // of the deoptimization information. | |
838 assert(dead_locals_are_killed(), "garbage in debug info before safepoint"); | |
839 | |
840 // Walk the inline list to fill in the correct set of JVMState's | |
841 // Also fill in the associated edges for each JVMState. | |
842 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
843 // If the bytecode needs to be reexecuted we need to put |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
844 // the arguments back on the stack. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
845 const bool should_reexecute = jvms()->should_reexecute(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
846 JVMState* youngest_jvms = should_reexecute ? sync_jvms_for_reexecute() : sync_jvms(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
847 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
848 // NOTE: set_bci (called from sync_jvms) might reset the reexecute bit to |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
849 // undefined if the bci is different. This is normal for Parse but it |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
850 // should not happen for LibraryCallKit because only one bci is processed. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
851 assert(!is_LibraryCallKit() || (jvms()->should_reexecute() == should_reexecute), |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
852 "in LibraryCallKit the reexecute bit should not change"); |
0 | 853 |
854 // If we are guaranteed to throw, we can prune everything but the | |
855 // input to the current bytecode. | |
856 bool can_prune_locals = false; | |
857 uint stack_slots_not_pruned = 0; | |
858 int inputs = 0, depth = 0; | |
859 if (must_throw) { | |
860 assert(method() == youngest_jvms->method(), "sanity"); | |
861 if (compute_stack_effects(inputs, depth)) { | |
862 can_prune_locals = true; | |
863 stack_slots_not_pruned = inputs; | |
864 } | |
865 } | |
866 | |
14477
96d2c94bbdd0
8035493: JVMTI PopFrame capability must instruct compilers not to prune locals
mgronlun
parents:
14223
diff
changeset
|
867 if (env()->should_retain_local_variables()) { |
0 | 868 // At any safepoint, this method can get breakpointed, which would |
869 // then require an immediate deoptimization. | |
870 can_prune_locals = false; // do not prune locals | |
871 stack_slots_not_pruned = 0; | |
872 } | |
873 | |
874 // do not scribble on the input jvms | |
875 JVMState* out_jvms = youngest_jvms->clone_deep(C); | |
876 call->set_jvms(out_jvms); // Start jvms list for call node | |
877 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
878 // For a known set of bytecodes, the interpreter should reexecute them if |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
879 // deoptimization happens. We set the reexecute state for them here |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
880 if (out_jvms->is_reexecute_undefined() && //don't change if already specified |
1252
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1166
diff
changeset
|
881 should_reexecute_implied_by_bytecode(out_jvms, call->is_AllocateArray())) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
882 out_jvms->set_should_reexecute(true); //NOTE: youngest_jvms not changed |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
883 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
851
diff
changeset
|
884 |
0 | 885 // Presize the call: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
886 DEBUG_ONLY(uint non_debug_edges = call->req()); |
0 | 887 call->add_req_batch(top(), youngest_jvms->debug_depth()); |
888 assert(call->req() == non_debug_edges + youngest_jvms->debug_depth(), ""); | |
889 | |
890 // Set up edges so that the call looks like this: | |
891 // Call [state:] ctl io mem fptr retadr | |
892 // [parms:] parm0 ... parmN | |
893 // [root:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN | |
894 // [...mid:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN [...] | |
895 // [young:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN | |
896 // Note that caller debug info precedes callee debug info. | |
897 | |
898 // Fill pointer walks backwards from "young:" to "root:" in the diagram above: | |
899 uint debug_ptr = call->req(); | |
900 | |
901 // Loop over the map input edges associated with jvms, add them | |
902 // to the call node, & reset all offsets to match call node array. | |
903 for (JVMState* in_jvms = youngest_jvms; in_jvms != NULL; ) { | |
904 uint debug_end = debug_ptr; | |
905 uint debug_start = debug_ptr - in_jvms->debug_size(); | |
906 debug_ptr = debug_start; // back up the ptr | |
907 | |
908 uint p = debug_start; // walks forward in [debug_start, debug_end) | |
909 uint j, k, l; | |
910 SafePointNode* in_map = in_jvms->map(); | |
911 out_jvms->set_map(call); | |
912 | |
913 if (can_prune_locals) { | |
914 assert(in_jvms->method() == out_jvms->method(), "sanity"); | |
915 // If the current throw can reach an exception handler in this JVMS, | |
916 // then we must keep everything live that can reach that handler. | |
917 // As a quick and dirty approximation, we look for any handlers at all. | |
918 if (in_jvms->method()->has_exception_handlers()) { | |
919 can_prune_locals = false; | |
920 } | |
921 } | |
922 | |
923 // Add the Locals | |
924 k = in_jvms->locoff(); | |
925 l = in_jvms->loc_size(); | |
926 out_jvms->set_locoff(p); | |
1397
b4776199210f
6943485: JVMTI always on capabilities change code generation too much
never
parents:
1257
diff
changeset
|
927 if (!can_prune_locals) { |
0 | 928 for (j = 0; j < l; j++) |
929 call->set_req(p++, in_map->in(k+j)); | |
930 } else { | |
931 p += l; // already set to top above by add_req_batch | |
932 } | |
933 | |
934 // Add the Expression Stack | |
935 k = in_jvms->stkoff(); | |
936 l = in_jvms->sp(); | |
937 out_jvms->set_stkoff(p); | |
1397
b4776199210f
6943485: JVMTI always on capabilities change code generation too much
never
parents:
1257
diff
changeset
|
938 if (!can_prune_locals) { |
0 | 939 for (j = 0; j < l; j++) |
940 call->set_req(p++, in_map->in(k+j)); | |
941 } else if (can_prune_locals && stack_slots_not_pruned != 0) { | |
942 // Divide stack into {S0,...,S1}, where S0 is set to top. | |
943 uint s1 = stack_slots_not_pruned; | |
944 stack_slots_not_pruned = 0; // for next iteration | |
945 if (s1 > l) s1 = l; | |
946 uint s0 = l - s1; | |
947 p += s0; // skip the tops preinstalled by add_req_batch | |
948 for (j = s0; j < l; j++) | |
949 call->set_req(p++, in_map->in(k+j)); | |
950 } else { | |
951 p += l; // already set to top above by add_req_batch | |
952 } | |
953 | |
954 // Add the Monitors | |
955 k = in_jvms->monoff(); | |
956 l = in_jvms->mon_size(); | |
957 out_jvms->set_monoff(p); | |
958 for (j = 0; j < l; j++) | |
959 call->set_req(p++, in_map->in(k+j)); | |
960 | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
961 // Copy any scalar object fields. |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
962 k = in_jvms->scloff(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
963 l = in_jvms->scl_size(); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
964 out_jvms->set_scloff(p); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
965 for (j = 0; j < l; j++) |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
966 call->set_req(p++, in_map->in(k+j)); |
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
967 |
0 | 968 // Finish the new jvms. |
969 out_jvms->set_endoff(p); | |
970 | |
971 assert(out_jvms->endoff() == debug_end, "fill ptr must match"); | |
972 assert(out_jvms->depth() == in_jvms->depth(), "depth must match"); | |
973 assert(out_jvms->loc_size() == in_jvms->loc_size(), "size must match"); | |
974 assert(out_jvms->mon_size() == in_jvms->mon_size(), "size must match"); | |
63
eac007780a58
6671807: (Escape Analysis) Add new ideal node to represent the state of a scalarized object at a safepoint
kvn
parents:
29
diff
changeset
|
975 assert(out_jvms->scl_size() == in_jvms->scl_size(), "size must match"); |
0 | 976 assert(out_jvms->debug_size() == in_jvms->debug_size(), "size must match"); |
977 | |
978 // Update the two tail pointers in parallel. | |
979 out_jvms = out_jvms->caller(); | |
980 in_jvms = in_jvms->caller(); | |
981 } | |
982 | |
983 assert(debug_ptr == non_debug_edges, "debug info must fit exactly"); | |
984 | |
985 // Test the correctness of JVMState::debug_xxx accessors: | |
986 assert(call->jvms()->debug_start() == non_debug_edges, ""); | |
987 assert(call->jvms()->debug_end() == call->req(), ""); | |
988 assert(call->jvms()->debug_depth() == call->req() - non_debug_edges, ""); | |
989 } | |
990 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
991 bool GraphKit::compute_stack_effects(int& inputs, int& depth) { |
0 | 992 Bytecodes::Code code = java_bc(); |
993 if (code == Bytecodes::_wide) { | |
994 code = method()->java_code_at_bci(bci() + 1); | |
995 } | |
996 | |
997 BasicType rtype = T_ILLEGAL; | |
998 int rsize = 0; | |
999 | |
1000 if (code != Bytecodes::_illegal) { | |
1001 depth = Bytecodes::depth(code); // checkcast=0, athrow=-1 | |
1002 rtype = Bytecodes::result_type(code); // checkcast=P, athrow=V | |
1003 if (rtype < T_CONFLICT) | |
1004 rsize = type2size[rtype]; | |
1005 } | |
1006 | |
1007 switch (code) { | |
1008 case Bytecodes::_illegal: | |
1009 return false; | |
1010 | |
1011 case Bytecodes::_ldc: | |
1012 case Bytecodes::_ldc_w: | |
1013 case Bytecodes::_ldc2_w: | |
1014 inputs = 0; | |
1015 break; | |
1016 | |
1017 case Bytecodes::_dup: inputs = 1; break; | |
1018 case Bytecodes::_dup_x1: inputs = 2; break; | |
1019 case Bytecodes::_dup_x2: inputs = 3; break; | |
1020 case Bytecodes::_dup2: inputs = 2; break; | |
1021 case Bytecodes::_dup2_x1: inputs = 3; break; | |
1022 case Bytecodes::_dup2_x2: inputs = 4; break; | |
1023 case Bytecodes::_swap: inputs = 2; break; | |
1024 case Bytecodes::_arraylength: inputs = 1; break; | |
1025 | |
1026 case Bytecodes::_getstatic: | |
1027 case Bytecodes::_putstatic: | |
1028 case Bytecodes::_getfield: | |
1029 case Bytecodes::_putfield: | |
1030 { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1031 bool ignored_will_link; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1032 ciField* field = method()->get_field_at_bci(bci(), ignored_will_link); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1033 int size = field->type()->size(); |
0 | 1034 bool is_get = (depth >= 0), is_static = (depth & 1); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1035 inputs = (is_static ? 0 : 1); |
0 | 1036 if (is_get) { |
1037 depth = size - inputs; | |
1038 } else { | |
1039 inputs += size; // putxxx pops the value from the stack | |
1040 depth = - inputs; | |
1041 } | |
1042 } | |
1043 break; | |
1044 | |
1045 case Bytecodes::_invokevirtual: | |
1046 case Bytecodes::_invokespecial: | |
1047 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
647
diff
changeset
|
1048 case Bytecodes::_invokedynamic: |
0 | 1049 case Bytecodes::_invokeinterface: |
1050 { | |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
1051 bool ignored_will_link; |
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
1052 ciSignature* declared_signature = NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1053 ciMethod* ignored_callee = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
1054 assert(declared_signature != NULL, "cannot be null"); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1055 inputs = declared_signature->arg_size_for_bc(code); |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6266
diff
changeset
|
1056 int size = declared_signature->return_type()->size(); |
0 | 1057 depth = size - inputs; |
1058 } | |
1059 break; | |
1060 | |
1061 case Bytecodes::_multianewarray: | |
1062 { | |
1063 ciBytecodeStream iter(method()); | |
1064 iter.reset_to_bci(bci()); | |
1065 iter.next(); | |
1066 inputs = iter.get_dimensions(); | |
1067 assert(rsize == 1, ""); | |
1068 depth = rsize - inputs; | |
1069 } | |
1070 break; | |
1071 | |
1072 case Bytecodes::_ireturn: | |
1073 case Bytecodes::_lreturn: | |
1074 case Bytecodes::_freturn: | |
1075 case Bytecodes::_dreturn: | |
1076 case Bytecodes::_areturn: | |
1077 assert(rsize = -depth, ""); | |
1078 inputs = rsize; | |
1079 break; | |
1080 | |
1081 case Bytecodes::_jsr: | |
1082 case Bytecodes::_jsr_w: | |
1083 inputs = 0; | |
1084 depth = 1; // S.B. depth=1, not zero | |
1085 break; | |
1086 | |
1087 default: | |
1088 // bytecode produces a typed result | |
1089 inputs = rsize - depth; | |
1090 assert(inputs >= 0, ""); | |
1091 break; | |
1092 } | |
1093 | |
1094 #ifdef ASSERT | |
1095 // spot check | |
1096 int outputs = depth + inputs; | |
1097 assert(outputs >= 0, "sanity"); | |
1098 switch (code) { | |
1099 case Bytecodes::_checkcast: assert(inputs == 1 && outputs == 1, ""); break; | |
1100 case Bytecodes::_athrow: assert(inputs == 1 && outputs == 0, ""); break; | |
1101 case Bytecodes::_aload_0: assert(inputs == 0 && outputs == 1, ""); break; | |
1102 case Bytecodes::_return: assert(inputs == 0 && outputs == 0, ""); break; | |
1103 case Bytecodes::_drem: assert(inputs == 4 && outputs == 2, ""); break; | |
1104 } | |
1105 #endif //ASSERT | |
1106 | |
1107 return true; | |
1108 } | |
1109 | |
1110 | |
1111 | |
1112 //------------------------------basic_plus_adr--------------------------------- | |
1113 Node* GraphKit::basic_plus_adr(Node* base, Node* ptr, Node* offset) { | |
1114 // short-circuit a common case | |
1115 if (offset == intcon(0)) return ptr; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1116 return _gvn.transform( new (C) AddPNode(base, ptr, offset) ); |
0 | 1117 } |
1118 | |
1119 Node* GraphKit::ConvI2L(Node* offset) { | |
1120 // short-circuit a common case | |
1121 jint offset_con = find_int_con(offset, Type::OffsetBot); | |
1122 if (offset_con != Type::OffsetBot) { | |
6846 | 1123 return longcon((jlong) offset_con); |
0 | 1124 } |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1125 return _gvn.transform( new (C) ConvI2LNode(offset)); |
0 | 1126 } |
1127 Node* GraphKit::ConvL2I(Node* offset) { | |
1128 // short-circuit a common case | |
1129 jlong offset_con = find_long_con(offset, (jlong)Type::OffsetBot); | |
1130 if (offset_con != (jlong)Type::OffsetBot) { | |
1131 return intcon((int) offset_con); | |
1132 } | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1133 return _gvn.transform( new (C) ConvL2INode(offset)); |
0 | 1134 } |
1135 | |
1136 //-------------------------load_object_klass----------------------------------- | |
1137 Node* GraphKit::load_object_klass(Node* obj) { | |
1138 // Special-case a fresh allocation to avoid building nodes: | |
1139 Node* akls = AllocateNode::Ideal_klass(obj, &_gvn); | |
1140 if (akls != NULL) return akls; | |
1141 Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
113
diff
changeset
|
1142 return _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), k_adr, TypeInstPtr::KLASS) ); |
0 | 1143 } |
1144 | |
1145 //-------------------------load_array_length----------------------------------- | |
1146 Node* GraphKit::load_array_length(Node* array) { | |
1147 // Special-case a fresh allocation to avoid building nodes: | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1148 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(array, &_gvn); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1149 Node *alen; |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1150 if (alloc == NULL) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1151 Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes()); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1152 alen = _gvn.transform( new (C) LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS)); |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1153 } else { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1154 alen = alloc->Ideal_length(); |
954
0f1c19b7a52d
6875619: CTW fails with /hotspot/src/share/vm/opto/type.hpp
kvn
parents:
950
diff
changeset
|
1155 Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn); |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1156 if (ccast != alen) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1157 alen = _gvn.transform(ccast); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1158 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1159 } |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
1160 return alen; |
0 | 1161 } |
1162 | |
1163 //------------------------------do_null_check---------------------------------- | |
1164 // Helper function to do a NULL pointer check. Returned value is | |
1165 // the incoming address with NULL casted away. You are allowed to use the | |
1166 // not-null value only if you are control dependent on the test. | |
1167 extern int explicit_null_checks_inserted, | |
1168 explicit_null_checks_elided; | |
1169 Node* GraphKit::null_check_common(Node* value, BasicType type, | |
1170 // optional arguments for variations: | |
1171 bool assert_null, | |
1172 Node* *null_control) { | |
1173 assert(!assert_null || null_control == NULL, "not both at once"); | |
1174 if (stopped()) return top(); | |
1175 if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) { | |
1176 // For some performance testing, we may wish to suppress null checking. | |
1177 value = cast_not_null(value); // Make it appear to be non-null (4962416). | |
1178 return value; | |
1179 } | |
1180 explicit_null_checks_inserted++; | |
1181 | |
1182 // Construct NULL check | |
1183 Node *chk = NULL; | |
1184 switch(type) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1185 case T_LONG : chk = new (C) CmpLNode(value, _gvn.zerocon(T_LONG)); break; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1186 case T_INT : chk = new (C) CmpINode(value, _gvn.intcon(0)); break; |
0 | 1187 case T_ARRAY : // fall through |
1188 type = T_OBJECT; // simplify further tests | |
1189 case T_OBJECT : { | |
1190 const Type *t = _gvn.type( value ); | |
1191 | |
950
8fe1963e3964
6875577: CTW fails with /hotspot/src/share/vm/opto/memnode.cpp
kvn
parents:
900
diff
changeset
|
1192 const TypeOopPtr* tp = t->isa_oopptr(); |
955 | 1193 if (tp != NULL && tp->klass() != NULL && !tp->klass()->is_loaded() |
0 | 1194 // Only for do_null_check, not any of its siblings: |
1195 && !assert_null && null_control == NULL) { | |
1196 // Usually, any field access or invocation on an unloaded oop type | |
1197 // will simply fail to link, since the statically linked class is | |
1198 // likely also to be unloaded. However, in -Xcomp mode, sometimes | |
1199 // the static class is loaded but the sharper oop type is not. | |
1200 // Rather than checking for this obscure case in lots of places, | |
1201 // we simply observe that a null check on an unloaded class | |
1202 // will always be followed by a nonsense operation, so we | |
1203 // can just issue the uncommon trap here. | |
1204 // Our access to the unloaded class will only be correct | |
1205 // after it has been loaded and initialized, which requires | |
1206 // a trip through the interpreter. | |
1207 #ifndef PRODUCT | |
1208 if (WizardMode) { tty->print("Null check of unloaded "); tp->klass()->print(); tty->cr(); } | |
1209 #endif | |
1210 uncommon_trap(Deoptimization::Reason_unloaded, | |
1211 Deoptimization::Action_reinterpret, | |
1212 tp->klass(), "!loaded"); | |
1213 return top(); | |
1214 } | |
1215 | |
1216 if (assert_null) { | |
1217 // See if the type is contained in NULL_PTR. | |
1218 // If so, then the value is already null. | |
1219 if (t->higher_equal(TypePtr::NULL_PTR)) { | |
1220 explicit_null_checks_elided++; | |
1221 return value; // Elided null assert quickly! | |
1222 } | |
1223 } else { | |
1224 // See if mixing in the NULL pointer changes type. | |
1225 // If so, then the NULL pointer was not allowed in the original | |
1226 // type. In other words, "value" was not-null. | |
14383
5ec7dace41a6
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
14223
diff
changeset
|
1227 if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) { |
0 | 1228 // same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ... |
1229 explicit_null_checks_elided++; | |
1230 return value; // Elided null check quickly! | |
1231 } | |
1232 } | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1233 chk = new (C) CmpPNode( value, null() ); |
0 | 1234 break; |
1235 } | |
1236 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1237 default: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1238 fatal(err_msg_res("unexpected type: %s", type2name(type))); |
0 | 1239 } |
1240 assert(chk != NULL, "sanity check"); | |
1241 chk = _gvn.transform(chk); | |
1242 | |
1243 BoolTest::mask btest = assert_null ? BoolTest::eq : BoolTest::ne; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1244 BoolNode *btst = new (C) BoolNode( chk, btest); |
0 | 1245 Node *tst = _gvn.transform( btst ); |
1246 | |
1247 //----------- | |
605 | 1248 // if peephole optimizations occurred, a prior test existed. |
0 | 1249 // If a prior test existed, maybe it dominates as we can avoid this test. |
1250 if (tst != btst && type == T_OBJECT) { | |
1251 // At this point we want to scan up the CFG to see if we can | |
1252 // find an identical test (and so avoid this test altogether). | |
1253 Node *cfg = control(); | |
1254 int depth = 0; | |
1255 while( depth < 16 ) { // Limit search depth for speed | |
1256 if( cfg->Opcode() == Op_IfTrue && | |
1257 cfg->in(0)->in(1) == tst ) { | |
1258 // Found prior test. Use "cast_not_null" to construct an identical | |
1259 // CastPP (and hence hash to) as already exists for the prior test. | |
1260 // Return that casted value. | |
1261 if (assert_null) { | |
1262 replace_in_map(value, null()); | |
1263 return null(); // do not issue the redundant test | |
1264 } | |
1265 Node *oldcontrol = control(); | |
1266 set_control(cfg); | |
1267 Node *res = cast_not_null(value); | |
1268 set_control(oldcontrol); | |
1269 explicit_null_checks_elided++; | |
1270 return res; | |
1271 } | |
1272 cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true); | |
1273 if (cfg == NULL) break; // Quit at region nodes | |
1274 depth++; | |
1275 } | |
1276 } | |
1277 | |
1278 //----------- | |
1279 // Branch to failure if null | |
1280 float ok_prob = PROB_MAX; // a priori estimate: nulls never happen | |
1281 Deoptimization::DeoptReason reason; | |
1282 if (assert_null) | |
1283 reason = Deoptimization::Reason_null_assert; | |
1284 else if (type == T_OBJECT) | |
1285 reason = Deoptimization::Reason_null_check; | |
1286 else | |
1287 reason = Deoptimization::Reason_div0_check; | |
1288 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1289 // %%% Since Reason_unhandled is not recorded on a per-bytecode basis, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1290 // ciMethodData::has_trap_at will return a conservative -1 if any |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1291 // must-be-null assertion has failed. This could cause performance |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1292 // problems for a method after its first do_null_assert failure. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1293 // Consider using 'Reason_class_check' instead? |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1294 |
0 | 1295 // To cause an implicit null check, we set the not-null probability |
605 | 1296 // to the maximum (PROB_MAX). For an explicit check the probability |
0 | 1297 // is set to a smaller value. |
1298 if (null_control != NULL || too_many_traps(reason)) { | |
1299 // probability is less likely | |
1300 ok_prob = PROB_LIKELY_MAG(3); | |
1301 } else if (!assert_null && | |
1302 (ImplicitNullCheckThreshold > 0) && | |
1303 method() != NULL && | |
1304 (method()->method_data()->trap_count(reason) | |
1305 >= (uint)ImplicitNullCheckThreshold)) { | |
1306 ok_prob = PROB_LIKELY_MAG(3); | |
1307 } | |
1308 | |
1309 if (null_control != NULL) { | |
1310 IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1311 Node* null_true = _gvn.transform( new (C) IfFalseNode(iff)); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1312 set_control( _gvn.transform( new (C) IfTrueNode(iff))); |
0 | 1313 if (null_true == top()) |
1314 explicit_null_checks_elided++; | |
1315 (*null_control) = null_true; | |
1316 } else { | |
1317 BuildCutout unless(this, tst, ok_prob); | |
1318 // Check for optimizer eliding test at parse time | |
1319 if (stopped()) { | |
1320 // Failure not possible; do not bother making uncommon trap. | |
1321 explicit_null_checks_elided++; | |
1322 } else if (assert_null) { | |
1323 uncommon_trap(reason, | |
1324 Deoptimization::Action_make_not_entrant, | |
1325 NULL, "assert_null"); | |
1326 } else { | |
332 | 1327 replace_in_map(value, zerocon(type)); |
0 | 1328 builtin_throw(reason); |
1329 } | |
1330 } | |
1331 | |
1332 // Must throw exception, fall-thru not possible? | |
1333 if (stopped()) { | |
1334 return top(); // No result | |
1335 } | |
1336 | |
1337 if (assert_null) { | |
1338 // Cast obj to null on this path. | |
1339 replace_in_map(value, zerocon(type)); | |
1340 return zerocon(type); | |
1341 } | |
1342 | |
1343 // Cast obj to not-null on this path, if there is no null_control. | |
1344 // (If there is a null_control, a non-null value may come back to haunt us.) | |
1345 if (type == T_OBJECT) { | |
1346 Node* cast = cast_not_null(value, false); | |
1347 if (null_control == NULL || (*null_control) == top()) | |
1348 replace_in_map(value, cast); | |
1349 value = cast; | |
1350 } | |
1351 | |
1352 return value; | |
1353 } | |
1354 | |
1355 | |
1356 //------------------------------cast_not_null---------------------------------- | |
1357 // Cast obj to not-null on this path | |
1358 Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) { | |
1359 const Type *t = _gvn.type(obj); | |
14383
5ec7dace41a6
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
14223
diff
changeset
|
1360 const Type *t_not_null = t->join_speculative(TypePtr::NOTNULL); |
0 | 1361 // Object is already not-null? |
1362 if( t == t_not_null ) return obj; | |
1363 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1364 Node *cast = new (C) CastPPNode(obj,t_not_null); |
0 | 1365 cast->init_req(0, control()); |
1366 cast = _gvn.transform( cast ); | |
1367 | |
1368 // Scan for instances of 'obj' in the current JVM mapping. | |
1369 // These instances are known to be not-null after the test. | |
1370 if (do_replace_in_map) | |
1371 replace_in_map(obj, cast); | |
1372 | |
1373 return cast; // Return casted value | |
1374 } | |
1375 | |
1376 | |
1377 //--------------------------replace_in_map------------------------------------- | |
1378 void GraphKit::replace_in_map(Node* old, Node* neww) { | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1379 if (old == neww) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1380 return; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1381 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1382 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1383 map()->replace_edge(old, neww); |
0 | 1384 |
1385 // Note: This operation potentially replaces any edge | |
1386 // on the map. This includes locals, stack, and monitors | |
1387 // of the current (innermost) JVM state. | |
1388 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1389 if (!ReplaceInParentMaps) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1390 return; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1391 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1392 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1393 // PreserveJVMState doesn't do a deep copy so we can't modify |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1394 // parents |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1395 if (Compile::current()->has_preserve_jvm_state()) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1396 return; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1397 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1398 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1399 Parse* parser = is_Parse(); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1400 bool progress = true; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1401 Node* ctrl = map()->in(0); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1402 // Follow the chain of parsers and see whether the update can be |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1403 // done in the map of callers. We can do the replace for a caller if |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1404 // the current control post dominates the control of a caller. |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1405 while (parser != NULL && parser->caller() != NULL && progress) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1406 progress = false; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1407 Node* parent_map = parser->caller()->map(); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1408 assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch"); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1409 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1410 Node* parent_ctrl = parent_map->in(0); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1411 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1412 while (parent_ctrl->is_Region()) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1413 Node* n = parent_ctrl->as_Region()->is_copy(); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1414 if (n == NULL) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1415 break; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1416 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1417 parent_ctrl = n; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1418 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1419 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1420 for (;;) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1421 if (ctrl == parent_ctrl) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1422 // update the map of the exits which is the one that will be |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1423 // used when compilation resume after inlining |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1424 parser->exits().map()->replace_edge(old, neww); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1425 progress = true; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1426 break; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1427 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1428 if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1429 ctrl = ctrl->in(0)->in(0); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1430 } else if (ctrl->is_Region()) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1431 Node* n = ctrl->as_Region()->is_copy(); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1432 if (n == NULL) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1433 break; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1434 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1435 ctrl = n; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1436 } else { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1437 break; |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1438 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1439 } |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1440 |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1441 parser = parser->parent_parser(); |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12886
diff
changeset
|
1442 } |
0 | 1443 } |
1444 | |
1445 | |
1446 //============================================================================= | |
1447 //--------------------------------memory--------------------------------------- | |
1448 Node* GraphKit::memory(uint alias_idx) { | |
1449 MergeMemNode* mem = merged_memory(); | |
1450 Node* p = mem->memory_at(alias_idx); | |
1451 _gvn.set_type(p, Type::MEMORY); // must be mapped | |
1452 return p; | |
1453 } | |
1454 | |
1455 //-----------------------------reset_memory------------------------------------ | |
1456 Node* GraphKit::reset_memory() { | |
1457 Node* mem = map()->memory(); | |
1458 // do not use this node for any more parsing! | |
1459 debug_only( map()->set_memory((Node*)NULL) ); | |
1460 return _gvn.transform( mem ); | |
1461 } | |
1462 | |
1463 //------------------------------set_all_memory--------------------------------- | |
1464 void GraphKit::set_all_memory(Node* newmem) { | |
1465 Node* mergemem = MergeMemNode::make(C, newmem); | |
1466 gvn().set_type_bottom(mergemem); | |
1467 map()->set_memory(mergemem); | |
1468 } | |
1469 | |
1470 //------------------------------set_all_memory_call---------------------------- | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1471 void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1472 Node* newmem = _gvn.transform( new (C) ProjNode(call, TypeFunc::Memory, separate_io_proj) ); |
0 | 1473 set_all_memory(newmem); |
1474 } | |
1475 | |
1476 //============================================================================= | |
1477 // | |
1478 // parser factory methods for MemNodes | |
1479 // | |
1480 // These are layered on top of the factory methods in LoadNode and StoreNode, | |
1481 // and integrate with the parser's memory state and _gvn engine. | |
1482 // | |
1483 | |
1484 // factory methods in "int adr_idx" | |
1485 Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, | |
1486 int adr_idx, | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1487 MemNode::MemOrd mo, bool require_atomic_access) { |
0 | 1488 assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); |
1489 const TypePtr* adr_type = NULL; // debug-mode-only argument | |
1490 debug_only(adr_type = C->get_adr_type(adr_idx)); | |
1491 Node* mem = memory(adr_idx); | |
1492 Node* ld; | |
1493 if (require_atomic_access && bt == T_LONG) { | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1494 ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); |
0 | 1495 } else { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1496 ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); |
0 | 1497 } |
10278 | 1498 ld = _gvn.transform(ld); |
1499 if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { | |
1500 // Improve graph before escape analysis and boxing elimination. | |
1501 record_for_igvn(ld); | |
1502 } | |
1503 return ld; | |
0 | 1504 } |
1505 | |
1506 Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, | |
1507 int adr_idx, | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1508 MemNode::MemOrd mo, |
0 | 1509 bool require_atomic_access) { |
1510 assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); | |
1511 const TypePtr* adr_type = NULL; | |
1512 debug_only(adr_type = C->get_adr_type(adr_idx)); | |
1513 Node *mem = memory(adr_idx); | |
1514 Node* st; | |
1515 if (require_atomic_access && bt == T_LONG) { | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1516 st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); |
0 | 1517 } else { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1518 st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); |
0 | 1519 } |
1520 st = _gvn.transform(st); | |
1521 set_memory(st, adr_idx); | |
1522 // Back-to-back stores can only remove intermediate store with DU info | |
1523 // so push on worklist for optimizer. | |
1524 if (mem->req() > MemNode::Address && adr == mem->in(MemNode::Address)) | |
1525 record_for_igvn(st); | |
1526 | |
1527 return st; | |
1528 } | |
1529 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1530 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1531 void GraphKit::pre_barrier(bool do_load, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1532 Node* ctl, |
0 | 1533 Node* obj, |
1534 Node* adr, | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1535 uint adr_idx, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1536 Node* val, |
825 | 1537 const TypeOopPtr* val_type, |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1538 Node* pre_val, |
0 | 1539 BasicType bt) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1540 |
0 | 1541 BarrierSet* bs = Universe::heap()->barrier_set(); |
1542 set_control(ctl); | |
1543 switch (bs->kind()) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1544 case BarrierSet::G1SATBCT: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1545 case BarrierSet::G1SATBCTLogging: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1546 g1_write_barrier_pre(do_load, obj, adr, adr_idx, val, val_type, pre_val, bt); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1547 break; |
0 | 1548 |
1549 case BarrierSet::CardTableModRef: | |
1550 case BarrierSet::CardTableExtension: | |
1551 case BarrierSet::ModRef: | |
1552 break; | |
1553 | |
1554 case BarrierSet::Other: | |
1555 default : | |
1556 ShouldNotReachHere(); | |
1557 | |
1558 } | |
1559 } | |
1560 | |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1561 bool GraphKit::can_move_pre_barrier() const { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1562 BarrierSet* bs = Universe::heap()->barrier_set(); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1563 switch (bs->kind()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1564 case BarrierSet::G1SATBCT: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1565 case BarrierSet::G1SATBCTLogging: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1566 return true; // Can move it if no safepoint |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1567 |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1568 case BarrierSet::CardTableModRef: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1569 case BarrierSet::CardTableExtension: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1570 case BarrierSet::ModRef: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1571 return true; // There is no pre-barrier |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1572 |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1573 case BarrierSet::Other: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1574 default : |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1575 ShouldNotReachHere(); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1576 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1577 return false; |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1578 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
1579 |
0 | 1580 void GraphKit::post_barrier(Node* ctl, |
1581 Node* store, | |
1582 Node* obj, | |
1583 Node* adr, | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1584 uint adr_idx, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1585 Node* val, |
0 | 1586 BasicType bt, |
1587 bool use_precise) { | |
1588 BarrierSet* bs = Universe::heap()->barrier_set(); | |
1589 set_control(ctl); | |
1590 switch (bs->kind()) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1591 case BarrierSet::G1SATBCT: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1592 case BarrierSet::G1SATBCTLogging: |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1593 g1_write_barrier_post(store, obj, adr, adr_idx, val, bt, use_precise); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1594 break; |
0 | 1595 |
1596 case BarrierSet::CardTableModRef: | |
1597 case BarrierSet::CardTableExtension: | |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
1598 write_barrier_post(store, obj, adr, adr_idx, val, use_precise); |
0 | 1599 break; |
1600 | |
1601 case BarrierSet::ModRef: | |
1602 break; | |
1603 | |
1604 case BarrierSet::Other: | |
1605 default : | |
1606 ShouldNotReachHere(); | |
1607 | |
1608 } | |
1609 } | |
1610 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1611 Node* GraphKit::store_oop(Node* ctl, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1612 Node* obj, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1613 Node* adr, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1614 const TypePtr* adr_type, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1615 Node* val, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1616 const TypeOopPtr* val_type, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1617 BasicType bt, |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1618 bool use_precise, |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1619 MemNode::MemOrd mo) { |
4894
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4763
diff
changeset
|
1620 // Transformation of a value which could be NULL pointer (CastPP #NULL) |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4763
diff
changeset
|
1621 // could be delayed during Parse (for example, in adjust_map_after_if()). |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4763
diff
changeset
|
1622 // Execute transformation here to avoid barrier generation in such case. |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4763
diff
changeset
|
1623 if (_gvn.type(val) == TypePtr::NULL_PTR) |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4763
diff
changeset
|
1624 val = _gvn.makecon(TypePtr::NULL_PTR); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1625 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1626 set_control(ctl); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1627 if (stopped()) return top(); // Dead path ? |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1628 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1629 assert(bt == T_OBJECT, "sanity"); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1630 assert(val != NULL, "not dead path"); |
0 | 1631 uint adr_idx = C->get_alias_index(adr_type); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1632 assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1633 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1634 pre_barrier(true /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1635 control(), obj, adr, adr_idx, val, val_type, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1636 NULL /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1637 bt); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
1638 |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1639 Node* store = store_to_memory(control(), adr, val, bt, adr_idx, mo); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1640 post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise); |
0 | 1641 return store; |
1642 } | |
1643 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1644 // Could be an array or object we don't know at compile time (unsafe ref.) |
0 | 1645 Node* GraphKit::store_oop_to_unknown(Node* ctl, |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1646 Node* obj, // containing obj |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1647 Node* adr, // actual adress to store val at |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1648 const TypePtr* adr_type, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
1649 Node* val, |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1650 BasicType bt, |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1651 MemNode::MemOrd mo) { |
825 | 1652 Compile::AliasType* at = C->alias_type(adr_type); |
1653 const TypeOopPtr* val_type = NULL; | |
1654 if (adr_type->isa_instptr()) { | |
1655 if (at->field() != NULL) { | |
1656 // known field. This code is a copy of the do_put_xxx logic. | |
1657 ciField* field = at->field(); | |
1658 if (!field->type()->is_loaded()) { | |
1659 val_type = TypeInstPtr::BOTTOM; | |
1660 } else { | |
1661 val_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); | |
1662 } | |
1663 } | |
1664 } else if (adr_type->isa_aryptr()) { | |
827
bf3489cc0aa0
6856025: assert(_base >= OopPtr && _base <= KlassPtr,"Not a Java pointer")
never
parents:
825
diff
changeset
|
1665 val_type = adr_type->is_aryptr()->elem()->make_oopptr(); |
825 | 1666 } |
1667 if (val_type == NULL) { | |
1668 val_type = TypeInstPtr::BOTTOM; | |
1669 } | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1670 return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo); |
0 | 1671 } |
1672 | |
1673 | |
1674 //-------------------------array_element_address------------------------- | |
1675 Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt, | |
1676 const TypeInt* sizetype) { | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
23
diff
changeset
|
1677 uint shift = exact_log2(type2aelembytes(elembt)); |
0 | 1678 uint header = arrayOopDesc::base_offset_in_bytes(elembt); |
1679 | |
1680 // short-circuit a common case (saves lots of confusing waste motion) | |
1681 jint idx_con = find_int_con(idx, -1); | |
1682 if (idx_con >= 0) { | |
1683 intptr_t offset = header + ((intptr_t)idx_con << shift); | |
1684 return basic_plus_adr(ary, offset); | |
1685 } | |
1686 | |
1687 // must be correct type for alignment purposes | |
1688 Node* base = basic_plus_adr(ary, header); | |
1689 #ifdef _LP64 | |
1690 // The scaled index operand to AddP must be a clean 64-bit value. | |
1691 // Java allows a 32-bit int to be incremented to a negative | |
1692 // value, which appears in a 64-bit register as a large | |
1693 // positive number. Using that large positive number as an | |
1694 // operand in pointer arithmetic has bad consequences. | |
1695 // On the other hand, 32-bit overflow is rare, and the possibility | |
1696 // can often be excluded, if we annotate the ConvI2L node with | |
1697 // a type assertion that its value is known to be a small positive | |
1698 // number. (The prior range check has ensured this.) | |
1699 // This assertion is used by ConvI2LNode::Ideal. | |
1700 int index_max = max_jint - 1; // array size is max_jint, index is one less | |
1701 if (sizetype != NULL) index_max = sizetype->_hi - 1; | |
1702 const TypeLong* lidxtype = TypeLong::make(CONST64(0), index_max, Type::WidenMax); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1703 idx = _gvn.transform( new (C) ConvI2LNode(idx, lidxtype) ); |
0 | 1704 #endif |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1705 Node* scale = _gvn.transform( new (C) LShiftXNode(idx, intcon(shift)) ); |
0 | 1706 return basic_plus_adr(ary, base, scale); |
1707 } | |
1708 | |
1709 //-------------------------load_array_element------------------------- | |
1710 Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype) { | |
1711 const Type* elemtype = arytype->elem(); | |
1712 BasicType elembt = elemtype->array_element_basic_type(); | |
1713 Node* adr = array_element_address(ary, idx, elembt, arytype->size()); | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1714 Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, MemNode::unordered); |
0 | 1715 return ld; |
1716 } | |
1717 | |
1718 //-------------------------set_arguments_for_java_call------------------------- | |
1719 // Arguments (pre-popped from the stack) are taken from the JVMS. | |
1720 void GraphKit::set_arguments_for_java_call(CallJavaNode* call) { | |
1721 // Add the call arguments: | |
1722 uint nargs = call->method()->arg_size(); | |
1723 for (uint i = 0; i < nargs; i++) { | |
1724 Node* arg = argument(i); | |
1725 call->init_req(i + TypeFunc::Parms, arg); | |
1726 } | |
1727 } | |
1728 | |
1729 //---------------------------set_edges_for_java_call--------------------------- | |
1730 // Connect a newly created call into the current JVMS. | |
1731 // A return value node (if any) is returned from set_edges_for_java_call. | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1732 void GraphKit::set_edges_for_java_call(CallJavaNode* call, bool must_throw, bool separate_io_proj) { |
0 | 1733 |
1734 // Add the predefined inputs: | |
1735 call->init_req( TypeFunc::Control, control() ); | |
1736 call->init_req( TypeFunc::I_O , i_o() ); | |
1737 call->init_req( TypeFunc::Memory , reset_memory() ); | |
1738 call->init_req( TypeFunc::FramePtr, frameptr() ); | |
1739 call->init_req( TypeFunc::ReturnAdr, top() ); | |
1740 | |
1741 add_safepoint_edges(call, must_throw); | |
1742 | |
1743 Node* xcall = _gvn.transform(call); | |
1744 | |
1745 if (xcall == top()) { | |
1746 set_control(top()); | |
1747 return; | |
1748 } | |
1749 assert(xcall == call, "call identity is stable"); | |
1750 | |
1751 // Re-use the current map to produce the result. | |
1752 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1753 set_control(_gvn.transform(new (C) ProjNode(call, TypeFunc::Control))); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1754 set_i_o( _gvn.transform(new (C) ProjNode(call, TypeFunc::I_O , separate_io_proj))); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1755 set_all_memory_call(xcall, separate_io_proj); |
0 | 1756 |
1757 //return xcall; // no need, caller already has it | |
1758 } | |
1759 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1760 Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) { |
0 | 1761 if (stopped()) return top(); // maybe the call folded up? |
1762 | |
1763 // Capture the return value, if any. | |
1764 Node* ret; | |
1765 if (call->method() == NULL || | |
1766 call->method()->return_type()->basic_type() == T_VOID) | |
1767 ret = top(); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1768 else ret = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
0 | 1769 |
1770 // Note: Since any out-of-line call can produce an exception, | |
1771 // we always insert an I_O projection from the call into the result. | |
1772 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1773 make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1774 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1775 if (separate_io_proj) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1776 // The caller requested separate projections be used by the fall |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1777 // through and exceptional paths, so replace the projections for |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1778 // the fall through path. |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1779 set_i_o(_gvn.transform( new (C) ProjNode(call, TypeFunc::I_O) )); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1780 set_all_memory(_gvn.transform( new (C) ProjNode(call, TypeFunc::Memory) )); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1781 } |
0 | 1782 return ret; |
1783 } | |
1784 | |
1785 //--------------------set_predefined_input_for_runtime_call-------------------- | |
1786 // Reading and setting the memory state is way conservative here. | |
1787 // The real problem is that I am not doing real Type analysis on memory, | |
1788 // so I cannot distinguish card mark stores from other stores. Across a GC | |
1789 // point the Store Barrier and the card mark memory has to agree. I cannot | |
1790 // have a card mark store and its barrier split across the GC point from | |
1791 // either above or below. Here I get that to happen by reading ALL of memory. | |
1792 // A better answer would be to separate out card marks from other memory. | |
1793 // For now, return the input memory state, so that it can be reused | |
1794 // after the call, if this call has restricted memory effects. | |
1795 Node* GraphKit::set_predefined_input_for_runtime_call(SafePointNode* call) { | |
1796 // Set fixed predefined input arguments | |
1797 Node* memory = reset_memory(); | |
1798 call->init_req( TypeFunc::Control, control() ); | |
1799 call->init_req( TypeFunc::I_O, top() ); // does no i/o | |
1800 call->init_req( TypeFunc::Memory, memory ); // may gc ptrs | |
1801 call->init_req( TypeFunc::FramePtr, frameptr() ); | |
1802 call->init_req( TypeFunc::ReturnAdr, top() ); | |
1803 return memory; | |
1804 } | |
1805 | |
1806 //-------------------set_predefined_output_for_runtime_call-------------------- | |
1807 // Set control and memory (not i_o) from the call. | |
1808 // If keep_mem is not NULL, use it for the output state, | |
1809 // except for the RawPtr output of the call, if hook_mem is TypeRawPtr::BOTTOM. | |
1810 // If hook_mem is NULL, this call produces no memory effects at all. | |
1811 // If hook_mem is a Java-visible memory slice (such as arraycopy operands), | |
1812 // then only that memory slice is taken from the call. | |
1813 // In the last case, we must put an appropriate memory barrier before | |
1814 // the call, so as to create the correct anti-dependencies on loads | |
1815 // preceding the call. | |
1816 void GraphKit::set_predefined_output_for_runtime_call(Node* call, | |
1817 Node* keep_mem, | |
1818 const TypePtr* hook_mem) { | |
1819 // no i/o | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1820 set_control(_gvn.transform( new (C) ProjNode(call,TypeFunc::Control) )); |
0 | 1821 if (keep_mem) { |
1822 // First clone the existing memory state | |
1823 set_all_memory(keep_mem); | |
1824 if (hook_mem != NULL) { | |
1825 // Make memory for the call | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1826 Node* mem = _gvn.transform( new (C) ProjNode(call, TypeFunc::Memory) ); |
0 | 1827 // Set the RawPtr memory state only. This covers all the heap top/GC stuff |
1828 // We also use hook_mem to extract specific effects from arraycopy stubs. | |
1829 set_memory(mem, hook_mem); | |
1830 } | |
1831 // ...else the call has NO memory effects. | |
1832 | |
1833 // Make sure the call advertises its memory effects precisely. | |
1834 // This lets us build accurate anti-dependences in gcm.cpp. | |
1835 assert(C->alias_type(call->adr_type()) == C->alias_type(hook_mem), | |
1836 "call node must be constructed correctly"); | |
1837 } else { | |
1838 assert(hook_mem == NULL, ""); | |
1839 // This is not a "slow path" call; all memory comes from the call. | |
1840 set_all_memory_call(call); | |
1841 } | |
1842 } | |
1843 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1844 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1845 // Replace the call with the current state of the kit. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1846 void GraphKit::replace_call(CallNode* call, Node* result) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1847 JVMState* ejvms = NULL; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1848 if (has_exceptions()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1849 ejvms = transfer_exceptions_into_jvms(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1850 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1851 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1852 SafePointNode* final_state = stop(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1853 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1854 // Find all the needed outputs of this call |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1855 CallProjections callprojs; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1856 call->extract_projections(&callprojs, true); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1857 |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1858 Node* init_mem = call->in(TypeFunc::Memory); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1859 Node* final_mem = final_state->in(TypeFunc::Memory); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1860 Node* final_ctl = final_state->in(TypeFunc::Control); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1861 Node* final_io = final_state->in(TypeFunc::I_O); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1862 |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1863 // Replace all the old call edges with the edges from the inlining result |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1864 if (callprojs.fallthrough_catchproj != NULL) { |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1865 C->gvn_replace_by(callprojs.fallthrough_catchproj, final_ctl); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1866 } |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1867 if (callprojs.fallthrough_memproj != NULL) { |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1868 C->gvn_replace_by(callprojs.fallthrough_memproj, final_mem); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1869 } |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1870 if (callprojs.fallthrough_ioproj != NULL) { |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1871 C->gvn_replace_by(callprojs.fallthrough_ioproj, final_io); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7196
diff
changeset
|
1872 } |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1873 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1874 // Replace the result with the new result if it exists and is used |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1875 if (callprojs.resproj != NULL && result != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1876 C->gvn_replace_by(callprojs.resproj, result); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1877 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1878 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1879 if (ejvms == NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1880 // No exception edges to simply kill off those paths |
7473 | 1881 if (callprojs.catchall_catchproj != NULL) { |
1882 C->gvn_replace_by(callprojs.catchall_catchproj, C->top()); | |
1883 } | |
1884 if (callprojs.catchall_memproj != NULL) { | |
1885 C->gvn_replace_by(callprojs.catchall_memproj, C->top()); | |
1886 } | |
1887 if (callprojs.catchall_ioproj != NULL) { | |
1888 C->gvn_replace_by(callprojs.catchall_ioproj, C->top()); | |
1889 } | |
1099
c5d3d979ae27
6908167: jbb2005, OptimizeStringConcat causes assert in EA
never
parents:
1080
diff
changeset
|
1890 // Replace the old exception object with top |
c5d3d979ae27
6908167: jbb2005, OptimizeStringConcat causes assert in EA
never
parents:
1080
diff
changeset
|
1891 if (callprojs.exobj != NULL) { |
c5d3d979ae27
6908167: jbb2005, OptimizeStringConcat causes assert in EA
never
parents:
1080
diff
changeset
|
1892 C->gvn_replace_by(callprojs.exobj, C->top()); |
c5d3d979ae27
6908167: jbb2005, OptimizeStringConcat causes assert in EA
never
parents:
1080
diff
changeset
|
1893 } |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1894 } else { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1895 GraphKit ekit(ejvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1896 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1897 // Load my combined exception state into the kit, with all phis transformed: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1898 SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1899 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1900 Node* ex_oop = ekit.use_exception_state(ex_map); |
7473 | 1901 if (callprojs.catchall_catchproj != NULL) { |
1902 C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control()); | |
1903 } | |
1904 if (callprojs.catchall_memproj != NULL) { | |
1905 C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory()); | |
1906 } | |
1907 if (callprojs.catchall_ioproj != NULL) { | |
1908 C->gvn_replace_by(callprojs.catchall_ioproj, ekit.i_o()); | |
1909 } | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1910 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1911 // Replace the old exception object with the newly created one |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1912 if (callprojs.exobj != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1913 C->gvn_replace_by(callprojs.exobj, ex_oop); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1914 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1915 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1916 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1917 // Disconnect the call from the graph |
7196
2aff40cb4703
7092905: C2: Keep track of the number of dead nodes
bharadwaj
parents:
7194
diff
changeset
|
1918 call->disconnect_inputs(NULL, C); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1919 C->gvn_replace_by(call, C->top()); |
1786
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1920 |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1921 // Clean up any MergeMems that feed other MergeMems since the |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1922 // optimizer doesn't like that. |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1923 if (final_mem->is_MergeMem()) { |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1924 Node_List wl; |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1925 for (SimpleDUIterator i(final_mem); i.has_next(); i.next()) { |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1926 Node* m = i.get(); |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1927 if (m->is_MergeMem() && !wl.contains(m)) { |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1928 wl.push(m); |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1929 } |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1930 } |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1931 while (wl.size() > 0) { |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1932 _gvn.transform(wl.pop()); |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1933 } |
f9883ee8ce39
6965815: OptimizeStringConcat: assert(!q->is_MergeMem()) failed with specjbb2000
never
parents:
1748
diff
changeset
|
1934 } |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1935 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1936 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
1027
diff
changeset
|
1937 |
0 | 1938 //------------------------------increment_counter------------------------------ |
1939 // for statistics: increment a VM counter by 1 | |
1940 | |
1941 void GraphKit::increment_counter(address counter_addr) { | |
1942 Node* adr1 = makecon(TypeRawPtr::make(counter_addr)); | |
1943 increment_counter(adr1); | |
1944 } | |
1945 | |
1946 void GraphKit::increment_counter(Node* counter_addr) { | |
1947 int adr_type = Compile::AliasIdxRaw; | |
1609 | 1948 Node* ctrl = control(); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1949 Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
1950 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
1951 store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, MemNode::unordered); |
0 | 1952 } |
1953 | |
1954 | |
1955 //------------------------------uncommon_trap---------------------------------- | |
1956 // Bail out to the interpreter in mid-method. Implemented by calling the | |
1957 // uncommon_trap blob. This helper function inserts a runtime call with the | |
1958 // right debug info. | |
1959 void GraphKit::uncommon_trap(int trap_request, | |
1960 ciKlass* klass, const char* comment, | |
1961 bool must_throw, | |
1962 bool keep_exact_action) { | |
1963 if (failing()) stop(); | |
1964 if (stopped()) return; // trap reachable? | |
1965 | |
1966 // Note: If ProfileTraps is true, and if a deopt. actually | |
1967 // occurs here, the runtime will make sure an MDO exists. There is | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
1972
diff
changeset
|
1968 // no need to call method()->ensure_method_data() at this point. |
0 | 1969 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1970 // Set the stack pointer to the right value for reexecution: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1971 set_sp(reexecute_sp()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1972 |
0 | 1973 #ifdef ASSERT |
1974 if (!must_throw) { | |
1975 // Make sure the stack has at least enough depth to execute | |
1976 // the current bytecode. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1977 int inputs, ignored_depth; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1978 if (compute_stack_effects(inputs, ignored_depth)) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1979 assert(sp() >= inputs, err_msg_res("must have enough JVMS stack to execute %s: sp=%d, inputs=%d", |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
1980 Bytecodes::name(java_bc()), sp(), inputs)); |
0 | 1981 } |
1982 } | |
1983 #endif | |
1984 | |
1985 Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request); | |
1986 Deoptimization::DeoptAction action = Deoptimization::trap_request_action(trap_request); | |
1987 | |
1988 switch (action) { | |
1989 case Deoptimization::Action_maybe_recompile: | |
1990 case Deoptimization::Action_reinterpret: | |
1991 // Temporary fix for 6529811 to allow virtual calls to be sure they | |
1992 // get the chance to go from mono->bi->mega | |
1993 if (!keep_exact_action && | |
1994 Deoptimization::trap_request_index(trap_request) < 0 && | |
1995 too_many_recompiles(reason)) { | |
1996 // This BCI is causing too many recompilations. | |
1997 action = Deoptimization::Action_none; | |
1998 trap_request = Deoptimization::make_trap_request(reason, action); | |
1999 } else { | |
2000 C->set_trap_can_recompile(true); | |
2001 } | |
2002 break; | |
2003 case Deoptimization::Action_make_not_entrant: | |
2004 C->set_trap_can_recompile(true); | |
2005 break; | |
2006 #ifdef ASSERT | |
2007 case Deoptimization::Action_none: | |
2008 case Deoptimization::Action_make_not_compilable: | |
2009 break; | |
2010 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
2011 fatal(err_msg_res("unknown action %d: %s", action, Deoptimization::trap_action_name(action))); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
2012 break; |
0 | 2013 #endif |
2014 } | |
2015 | |
2016 if (TraceOptoParse) { | |
2017 char buf[100]; | |
2018 tty->print_cr("Uncommon trap %s at bci:%d", | |
2019 Deoptimization::format_trap_request(buf, sizeof(buf), | |
2020 trap_request), bci()); | |
2021 } | |
2022 | |
2023 CompileLog* log = C->log(); | |
2024 if (log != NULL) { | |
2025 int kid = (klass == NULL)? -1: log->identify(klass); | |
2026 log->begin_elem("uncommon_trap bci='%d'", bci()); | |
2027 char buf[100]; | |
2028 log->print(" %s", Deoptimization::format_trap_request(buf, sizeof(buf), | |
2029 trap_request)); | |
2030 if (kid >= 0) log->print(" klass='%d'", kid); | |
2031 if (comment != NULL) log->print(" comment='%s'", comment); | |
2032 log->end_elem(); | |
2033 } | |
2034 | |
2035 // Make sure any guarding test views this path as very unlikely | |
2036 Node *i0 = control()->in(0); | |
2037 if (i0 != NULL && i0->is_If()) { // Found a guarding if test? | |
2038 IfNode *iff = i0->as_If(); | |
2039 float f = iff->_prob; // Get prob | |
2040 if (control()->Opcode() == Op_IfTrue) { | |
2041 if (f > PROB_UNLIKELY_MAG(4)) | |
2042 iff->_prob = PROB_MIN; | |
2043 } else { | |
2044 if (f < PROB_LIKELY_MAG(4)) | |
2045 iff->_prob = PROB_MAX; | |
2046 } | |
2047 } | |
2048 | |
2049 // Clear out dead values from the debug info. | |
2050 kill_dead_locals(); | |
2051 | |
2052 // Now insert the uncommon trap subroutine call | |
1748 | 2053 address call_addr = SharedRuntime::uncommon_trap_blob()->entry_point(); |
0 | 2054 const TypePtr* no_memory_effects = NULL; |
2055 // Pass the index of the class to be loaded | |
2056 Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON | | |
2057 (must_throw ? RC_MUST_THROW : 0), | |
2058 OptoRuntime::uncommon_trap_Type(), | |
2059 call_addr, "uncommon_trap", no_memory_effects, | |
2060 intcon(trap_request)); | |
2061 assert(call->as_CallStaticJava()->uncommon_trap_request() == trap_request, | |
2062 "must extract request correctly from the graph"); | |
2063 assert(trap_request != 0, "zero value reserved by uncommon_trap_request"); | |
2064 | |
2065 call->set_req(TypeFunc::ReturnAdr, returnadr()); | |
2066 // The debug info is the only real input to this call. | |
2067 | |
2068 // Halt-and-catch fire here. The above call should never return! | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2069 HaltNode* halt = new(C) HaltNode(control(), frameptr()); |
0 | 2070 _gvn.set_type_bottom(halt); |
2071 root()->add_req(halt); | |
2072 | |
2073 stop_and_kill_map(); | |
2074 } | |
2075 | |
2076 | |
2077 //--------------------------just_allocated_object------------------------------ | |
2078 // Report the object that was just allocated. | |
2079 // It must be the case that there are no intervening safepoints. | |
2080 // We use this to determine if an object is so "fresh" that | |
2081 // it does not require card marks. | |
2082 Node* GraphKit::just_allocated_object(Node* current_control) { | |
2083 if (C->recent_alloc_ctl() == current_control) | |
2084 return C->recent_alloc_obj(); | |
2085 return NULL; | |
2086 } | |
2087 | |
2088 | |
2089 void GraphKit::round_double_arguments(ciMethod* dest_method) { | |
2090 // (Note: TypeFunc::make has a cache that makes this fast.) | |
2091 const TypeFunc* tf = TypeFunc::make(dest_method); | |
2092 int nargs = tf->_domain->_cnt - TypeFunc::Parms; | |
2093 for (int j = 0; j < nargs; j++) { | |
2094 const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); | |
2095 if( targ->basic_type() == T_DOUBLE ) { | |
2096 // If any parameters are doubles, they must be rounded before | |
2097 // the call, dstore_rounding does gvn.transform | |
2098 Node *arg = argument(j); | |
2099 arg = dstore_rounding(arg); | |
2100 set_argument(j, arg); | |
2101 } | |
2102 } | |
2103 } | |
2104 | |
12966 | 2105 /** |
2106 * Record profiling data exact_kls for Node n with the type system so | |
2107 * that it can propagate it (speculation) | |
2108 * | |
2109 * @param n node that the type applies to | |
2110 * @param exact_kls type from profiling | |
2111 * | |
2112 * @return node with improved type | |
2113 */ | |
2114 Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { | |
2115 const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr(); | |
2116 assert(UseTypeSpeculation, "type speculation must be on"); | |
2117 if (exact_kls != NULL && | |
2118 // nothing to improve if type is already exact | |
2119 (current_type == NULL || | |
2120 (!current_type->klass_is_exact() && | |
2121 (current_type->speculative() == NULL || | |
2122 !current_type->speculative()->klass_is_exact())))) { | |
2123 const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); | |
2124 const TypeOopPtr* xtype = tklass->as_instance_type(); | |
2125 assert(xtype->klass_is_exact(), "Should be exact"); | |
2126 | |
2127 // Build a type with a speculative type (what we think we know | |
2128 // about the type but will need a guard when we use it) | |
2129 const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype); | |
2130 // We're changing the type, we need a new cast node to carry the | |
2131 // new type. The new type depends on the control: what profiling | |
2132 // tells us is only valid from here as far as we can tell. | |
2133 Node* cast = new(C) CastPPNode(n, spec_type); | |
2134 cast->init_req(0, control()); | |
2135 cast = _gvn.transform(cast); | |
2136 replace_in_map(n, cast); | |
2137 n = cast; | |
2138 } | |
2139 return n; | |
2140 } | |
2141 | |
2142 /** | |
2143 * Record profiling data from receiver profiling at an invoke with the | |
2144 * type system so that it can propagate it (speculation) | |
2145 * | |
2146 * @param n receiver node | |
2147 * | |
2148 * @return node with improved type | |
2149 */ | |
2150 Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) { | |
2151 if (!UseTypeSpeculation) { | |
2152 return n; | |
2153 } | |
2154 ciKlass* exact_kls = profile_has_unique_klass(); | |
2155 return record_profile_for_speculation(n, exact_kls); | |
2156 } | |
2157 | |
2158 /** | |
2159 * Record profiling data from argument profiling at an invoke with the | |
2160 * type system so that it can propagate it (speculation) | |
2161 * | |
2162 * @param dest_method target method for the call | |
2163 * @param bc what invoke bytecode is this? | |
2164 */ | |
2165 void GraphKit::record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc) { | |
2166 if (!UseTypeSpeculation) { | |
2167 return; | |
2168 } | |
2169 const TypeFunc* tf = TypeFunc::make(dest_method); | |
2170 int nargs = tf->_domain->_cnt - TypeFunc::Parms; | |
2171 int skip = Bytecodes::has_receiver(bc) ? 1 : 0; | |
2172 for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) { | |
2173 const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); | |
2174 if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) { | |
2175 ciKlass* better_type = method()->argument_profiled_type(bci(), i); | |
2176 if (better_type != NULL) { | |
2177 record_profile_for_speculation(argument(j), better_type); | |
2178 } | |
2179 i++; | |
2180 } | |
2181 } | |
2182 } | |
2183 | |
2184 /** | |
2185 * Record profiling data from parameter profiling at an invoke with | |
2186 * the type system so that it can propagate it (speculation) | |
2187 */ | |
2188 void GraphKit::record_profiled_parameters_for_speculation() { | |
2189 if (!UseTypeSpeculation) { | |
2190 return; | |
2191 } | |
2192 for (int i = 0, j = 0; i < method()->arg_size() ; i++) { | |
2193 if (_gvn.type(local(i))->isa_oopptr()) { | |
2194 ciKlass* better_type = method()->parameter_profiled_type(j); | |
2195 if (better_type != NULL) { | |
2196 record_profile_for_speculation(local(i), better_type); | |
2197 } | |
2198 j++; | |
2199 } | |
2200 } | |
2201 } | |
2202 | |
0 | 2203 void GraphKit::round_double_result(ciMethod* dest_method) { |
2204 // A non-strict method may return a double value which has an extended | |
2205 // exponent, but this must not be visible in a caller which is 'strict' | |
2206 // If a strict caller invokes a non-strict callee, round a double result | |
2207 | |
2208 BasicType result_type = dest_method->return_type()->basic_type(); | |
2209 assert( method() != NULL, "must have caller context"); | |
2210 if( result_type == T_DOUBLE && method()->is_strict() && !dest_method->is_strict() ) { | |
2211 // Destination method's return value is on top of stack | |
2212 // dstore_rounding() does gvn.transform | |
2213 Node *result = pop_pair(); | |
2214 result = dstore_rounding(result); | |
2215 push_pair(result); | |
2216 } | |
2217 } | |
2218 | |
2219 // rounding for strict float precision conformance | |
2220 Node* GraphKit::precision_rounding(Node* n) { | |
2221 return UseStrictFP && _method->flags().is_strict() | |
2222 && UseSSE == 0 && Matcher::strict_fp_requires_explicit_rounding | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2223 ? _gvn.transform( new (C) RoundFloatNode(0, n) ) |
0 | 2224 : n; |
2225 } | |
2226 | |
2227 // rounding for strict double precision conformance | |
2228 Node* GraphKit::dprecision_rounding(Node *n) { | |
2229 return UseStrictFP && _method->flags().is_strict() | |
2230 && UseSSE <= 1 && Matcher::strict_fp_requires_explicit_rounding | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2231 ? _gvn.transform( new (C) RoundDoubleNode(0, n) ) |
0 | 2232 : n; |
2233 } | |
2234 | |
2235 // rounding for non-strict double stores | |
2236 Node* GraphKit::dstore_rounding(Node* n) { | |
2237 return Matcher::strict_fp_requires_explicit_rounding | |
2238 && UseSSE <= 1 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2239 ? _gvn.transform( new (C) RoundDoubleNode(0, n) ) |
0 | 2240 : n; |
2241 } | |
2242 | |
2243 //============================================================================= | |
2244 // Generate a fast path/slow path idiom. Graph looks like: | |
2245 // [foo] indicates that 'foo' is a parameter | |
2246 // | |
2247 // [in] NULL | |
2248 // \ / | |
2249 // CmpP | |
2250 // Bool ne | |
2251 // If | |
2252 // / \ | |
2253 // True False-<2> | |
2254 // / | | |
2255 // / cast_not_null | |
2256 // Load | | ^ | |
2257 // [fast_test] | | | |
2258 // gvn to opt_test | | | |
2259 // / \ | <1> | |
2260 // True False | | |
2261 // | \\ | | |
2262 // [slow_call] \[fast_result] | |
2263 // Ctl Val \ \ | |
2264 // | \ \ | |
2265 // Catch <1> \ \ | |
2266 // / \ ^ \ \ | |
2267 // Ex No_Ex | \ \ | |
2268 // | \ \ | \ <2> \ | |
2269 // ... \ [slow_res] | | \ [null_result] | |
2270 // \ \--+--+--- | | | |
2271 // \ | / \ | / | |
2272 // --------Region Phi | |
2273 // | |
2274 //============================================================================= | |
2275 // Code is structured as a series of driver functions all called 'do_XXX' that | |
2276 // call a set of helper functions. Helper functions first, then drivers. | |
2277 | |
2278 //------------------------------null_check_oop--------------------------------- | |
2279 // Null check oop. Set null-path control into Region in slot 3. | |
2280 // Make a cast-not-nullness use the other not-null control. Return cast. | |
2281 Node* GraphKit::null_check_oop(Node* value, Node* *null_control, | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2282 bool never_see_null, bool safe_for_replace) { |
0 | 2283 // Initial NULL check taken path |
2284 (*null_control) = top(); | |
2285 Node* cast = null_check_common(value, T_OBJECT, false, null_control); | |
2286 | |
2287 // Generate uncommon_trap: | |
2288 if (never_see_null && (*null_control) != top()) { | |
2289 // If we see an unexpected null at a check-cast we record it and force a | |
2290 // recompile; the offending check-cast will be compiled to handle NULLs. | |
2291 // If we see more than one offending BCI, then all checkcasts in the | |
2292 // method will be compiled to handle NULLs. | |
2293 PreserveJVMState pjvms(this); | |
2294 set_control(*null_control); | |
332 | 2295 replace_in_map(value, null()); |
0 | 2296 uncommon_trap(Deoptimization::Reason_null_check, |
2297 Deoptimization::Action_make_not_entrant); | |
2298 (*null_control) = top(); // NULL path is dead | |
2299 } | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2300 if ((*null_control) == top() && safe_for_replace) { |
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2301 replace_in_map(value, cast); |
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2302 } |
0 | 2303 |
2304 // Cast away null-ness on the result | |
2305 return cast; | |
2306 } | |
2307 | |
2308 //------------------------------opt_iff---------------------------------------- | |
2309 // Optimize the fast-check IfNode. Set the fast-path region slot 2. | |
2310 // Return slow-path control. | |
2311 Node* GraphKit::opt_iff(Node* region, Node* iff) { | |
2312 IfNode *opt_iff = _gvn.transform(iff)->as_If(); | |
2313 | |
2314 // Fast path taken; set region slot 2 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2315 Node *fast_taken = _gvn.transform( new (C) IfFalseNode(opt_iff) ); |
0 | 2316 region->init_req(2,fast_taken); // Capture fast-control |
2317 | |
2318 // Fast path not-taken, i.e. slow path | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2319 Node *slow_taken = _gvn.transform( new (C) IfTrueNode(opt_iff) ); |
0 | 2320 return slow_taken; |
2321 } | |
2322 | |
2323 //-----------------------------make_runtime_call------------------------------- | |
2324 Node* GraphKit::make_runtime_call(int flags, | |
2325 const TypeFunc* call_type, address call_addr, | |
2326 const char* call_name, | |
2327 const TypePtr* adr_type, | |
2328 // The following parms are all optional. | |
2329 // The first NULL ends the list. | |
2330 Node* parm0, Node* parm1, | |
2331 Node* parm2, Node* parm3, | |
2332 Node* parm4, Node* parm5, | |
2333 Node* parm6, Node* parm7) { | |
2334 // Slow-path call | |
2335 bool is_leaf = !(flags & RC_NO_LEAF); | |
2336 bool has_io = (!is_leaf && !(flags & RC_NO_IO)); | |
2337 if (call_name == NULL) { | |
2338 assert(!is_leaf, "must supply name for leaf"); | |
2339 call_name = OptoRuntime::stub_name(call_addr); | |
2340 } | |
2341 CallNode* call; | |
2342 if (!is_leaf) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2343 call = new(C) CallStaticJavaNode(call_type, call_addr, call_name, |
0 | 2344 bci(), adr_type); |
2345 } else if (flags & RC_NO_FP) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2346 call = new(C) CallLeafNoFPNode(call_type, call_addr, call_name, adr_type); |
0 | 2347 } else { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2348 call = new(C) CallLeafNode(call_type, call_addr, call_name, adr_type); |
0 | 2349 } |
2350 | |
2351 // The following is similar to set_edges_for_java_call, | |
2352 // except that the memory effects of the call are restricted to AliasIdxRaw. | |
2353 | |
2354 // Slow path call has no side-effects, uses few values | |
2355 bool wide_in = !(flags & RC_NARROW_MEM); | |
2356 bool wide_out = (C->get_alias_index(adr_type) == Compile::AliasIdxBot); | |
2357 | |
2358 Node* prev_mem = NULL; | |
2359 if (wide_in) { | |
2360 prev_mem = set_predefined_input_for_runtime_call(call); | |
2361 } else { | |
2362 assert(!wide_out, "narrow in => narrow out"); | |
2363 Node* narrow_mem = memory(adr_type); | |
2364 prev_mem = reset_memory(); | |
2365 map()->set_memory(narrow_mem); | |
2366 set_predefined_input_for_runtime_call(call); | |
2367 } | |
2368 | |
2369 // Hook each parm in order. Stop looking at the first NULL. | |
2370 if (parm0 != NULL) { call->init_req(TypeFunc::Parms+0, parm0); | |
2371 if (parm1 != NULL) { call->init_req(TypeFunc::Parms+1, parm1); | |
2372 if (parm2 != NULL) { call->init_req(TypeFunc::Parms+2, parm2); | |
2373 if (parm3 != NULL) { call->init_req(TypeFunc::Parms+3, parm3); | |
2374 if (parm4 != NULL) { call->init_req(TypeFunc::Parms+4, parm4); | |
2375 if (parm5 != NULL) { call->init_req(TypeFunc::Parms+5, parm5); | |
2376 if (parm6 != NULL) { call->init_req(TypeFunc::Parms+6, parm6); | |
2377 if (parm7 != NULL) { call->init_req(TypeFunc::Parms+7, parm7); | |
2378 /* close each nested if ===> */ } } } } } } } } | |
2379 assert(call->in(call->req()-1) != NULL, "must initialize all parms"); | |
2380 | |
2381 if (!is_leaf) { | |
2382 // Non-leaves can block and take safepoints: | |
2383 add_safepoint_edges(call, ((flags & RC_MUST_THROW) != 0)); | |
2384 } | |
2385 // Non-leaves can throw exceptions: | |
2386 if (has_io) { | |
2387 call->set_req(TypeFunc::I_O, i_o()); | |
2388 } | |
2389 | |
2390 if (flags & RC_UNCOMMON) { | |
2391 // Set the count to a tiny probability. Cf. Estimate_Block_Frequency. | |
2392 // (An "if" probability corresponds roughly to an unconditional count. | |
2393 // Sort of.) | |
2394 call->set_cnt(PROB_UNLIKELY_MAG(4)); | |
2395 } | |
2396 | |
2397 Node* c = _gvn.transform(call); | |
2398 assert(c == call, "cannot disappear"); | |
2399 | |
2400 if (wide_out) { | |
2401 // Slow path call has full side-effects. | |
2402 set_predefined_output_for_runtime_call(call); | |
2403 } else { | |
2404 // Slow path call has few side-effects, and/or sets few values. | |
2405 set_predefined_output_for_runtime_call(call, prev_mem, adr_type); | |
2406 } | |
2407 | |
2408 if (has_io) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2409 set_i_o(_gvn.transform(new (C) ProjNode(call, TypeFunc::I_O))); |
0 | 2410 } |
2411 return call; | |
2412 | |
2413 } | |
2414 | |
2415 //------------------------------merge_memory----------------------------------- | |
2416 // Merge memory from one path into the current memory state. | |
2417 void GraphKit::merge_memory(Node* new_mem, Node* region, int new_path) { | |
2418 for (MergeMemStream mms(merged_memory(), new_mem->as_MergeMem()); mms.next_non_empty2(); ) { | |
2419 Node* old_slice = mms.force_memory(); | |
2420 Node* new_slice = mms.memory2(); | |
2421 if (old_slice != new_slice) { | |
2422 PhiNode* phi; | |
2423 if (new_slice->is_Phi() && new_slice->as_Phi()->region() == region) { | |
2424 phi = new_slice->as_Phi(); | |
2425 #ifdef ASSERT | |
2426 if (old_slice->is_Phi() && old_slice->as_Phi()->region() == region) | |
2427 old_slice = old_slice->in(new_path); | |
2428 // Caller is responsible for ensuring that any pre-existing | |
2429 // phis are already aware of old memory. | |
2430 int old_path = (new_path > 1) ? 1 : 2; // choose old_path != new_path | |
2431 assert(phi->in(old_path) == old_slice, "pre-existing phis OK"); | |
2432 #endif | |
2433 mms.set_memory(phi); | |
2434 } else { | |
2435 phi = PhiNode::make(region, old_slice, Type::MEMORY, mms.adr_type(C)); | |
2436 _gvn.set_type(phi, Type::MEMORY); | |
2437 phi->set_req(new_path, new_slice); | |
2438 mms.set_memory(_gvn.transform(phi)); // assume it is complete | |
2439 } | |
2440 } | |
2441 } | |
2442 } | |
2443 | |
2444 //------------------------------make_slow_call_ex------------------------------ | |
2445 // Make the exception handler hookups for the slow call | |
2446 void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj) { | |
2447 if (stopped()) return; | |
2448 | |
2449 // Make a catch node with just two handlers: fall-through and catch-all | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2450 Node* i_o = _gvn.transform( new (C) ProjNode(call, TypeFunc::I_O, separate_io_proj) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2451 Node* catc = _gvn.transform( new (C) CatchNode(control(), i_o, 2) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2452 Node* norm = _gvn.transform( new (C) CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2453 Node* excp = _gvn.transform( new (C) CatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) ); |
0 | 2454 |
2455 { PreserveJVMState pjvms(this); | |
2456 set_control(excp); | |
2457 set_i_o(i_o); | |
2458 | |
2459 if (excp != top()) { | |
2460 // Create an exception state also. | |
2461 // Use an exact type if the caller has specified a specific exception. | |
2462 const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2463 Node* ex_oop = new (C) CreateExNode(ex_type, control(), i_o); |
0 | 2464 add_exception_state(make_exception_state(_gvn.transform(ex_oop))); |
2465 } | |
2466 } | |
2467 | |
2468 // Get the no-exception control from the CatchNode. | |
2469 set_control(norm); | |
2470 } | |
2471 | |
2472 | |
2473 //-------------------------------gen_subtype_check----------------------------- | |
2474 // Generate a subtyping check. Takes as input the subtype and supertype. | |
2475 // Returns 2 values: sets the default control() to the true path and returns | |
2476 // the false path. Only reads invariant memory; sets no (visible) memory. | |
2477 // The PartialSubtypeCheckNode sets the hidden 1-word cache in the encoding | |
2478 // but that's not exposed to the optimizer. This call also doesn't take in an | |
2479 // Object; if you wish to check an Object you need to load the Object's class | |
2480 // prior to coming here. | |
2481 Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { | |
2482 // Fast check for identical types, perhaps identical constants. | |
2483 // The types can even be identical non-constants, in cases | |
2484 // involving Array.newInstance, Object.clone, etc. | |
2485 if (subklass == superklass) | |
2486 return top(); // false path is dead; no test needed. | |
2487 | |
2488 if (_gvn.type(superklass)->singleton()) { | |
2489 ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); | |
2490 ciKlass* subk = _gvn.type(subklass)->is_klassptr()->klass(); | |
2491 | |
2492 // In the common case of an exact superklass, try to fold up the | |
2493 // test before generating code. You may ask, why not just generate | |
2494 // the code and then let it fold up? The answer is that the generated | |
2495 // code will necessarily include null checks, which do not always | |
2496 // completely fold away. If they are also needless, then they turn | |
2497 // into a performance loss. Example: | |
2498 // Foo[] fa = blah(); Foo x = fa[0]; fa[1] = x; | |
2499 // Here, the type of 'fa' is often exact, so the store check | |
2500 // of fa[1]=x will fold up, without testing the nullness of x. | |
2501 switch (static_subtype_check(superk, subk)) { | |
2502 case SSC_always_false: | |
2503 { | |
2504 Node* always_fail = control(); | |
2505 set_control(top()); | |
2506 return always_fail; | |
2507 } | |
2508 case SSC_always_true: | |
2509 return top(); | |
2510 case SSC_easy_test: | |
2511 { | |
2512 // Just do a direct pointer compare and be done. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2513 Node* cmp = _gvn.transform( new(C) CmpPNode(subklass, superklass) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2514 Node* bol = _gvn.transform( new(C) BoolNode(cmp, BoolTest::eq) ); |
0 | 2515 IfNode* iff = create_and_xform_if(control(), bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2516 set_control( _gvn.transform( new(C) IfTrueNode (iff) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2517 return _gvn.transform( new(C) IfFalseNode(iff) ); |
0 | 2518 } |
2519 case SSC_full_test: | |
2520 break; | |
2521 default: | |
2522 ShouldNotReachHere(); | |
2523 } | |
2524 } | |
2525 | |
2526 // %%% Possible further optimization: Even if the superklass is not exact, | |
2527 // if the subklass is the unique subtype of the superklass, the check | |
2528 // will always succeed. We could leave a dependency behind to ensure this. | |
2529 | |
2530 // First load the super-klass's check-offset | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3849
diff
changeset
|
2531 Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
2532 Node *chk_off = _gvn.transform(new (C) LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(), |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
2533 TypeInt::INT, MemNode::unordered)); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3849
diff
changeset
|
2534 int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); |
0 | 2535 bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); |
2536 | |
2537 // Load from the sub-klass's super-class display list, or a 1-word cache of | |
2538 // the secondary superclass list, or a failing value with a sentinel offset | |
2539 // if the super-klass is an interface or exceptionally deep in the Java | |
2540 // hierarchy and we have to scan the secondary superclass list the hard way. | |
2541 // Worst-case type is a little odd: NULL is allowed as a result (usually | |
2542 // klass loads can never produce a NULL). | |
2543 Node *chk_off_X = ConvI2X(chk_off); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2544 Node *p2 = _gvn.transform( new (C) AddPNode(subklass,subklass,chk_off_X) ); |
0 | 2545 // For some types like interfaces the following loadKlass is from a 1-word |
2546 // cache which is mutable so can't use immutable memory. Other | |
2547 // types load from the super-class display table which is immutable. | |
2548 Node *kmem = might_be_cache ? memory(p2) : immutable_memory(); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
113
diff
changeset
|
2549 Node *nkls = _gvn.transform( LoadKlassNode::make( _gvn, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) ); |
0 | 2550 |
2551 // Compile speed common case: ARE a subtype and we canNOT fail | |
2552 if( superklass == nkls ) | |
2553 return top(); // false path is dead; no test needed. | |
2554 | |
2555 // See if we get an immediate positive hit. Happens roughly 83% of the | |
2556 // time. Test to see if the value loaded just previously from the subklass | |
2557 // is exactly the superklass. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2558 Node *cmp1 = _gvn.transform( new (C) CmpPNode( superklass, nkls ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2559 Node *bol1 = _gvn.transform( new (C) BoolNode( cmp1, BoolTest::eq ) ); |
0 | 2560 IfNode *iff1 = create_and_xform_if( control(), bol1, PROB_LIKELY(0.83f), COUNT_UNKNOWN ); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2561 Node *iftrue1 = _gvn.transform( new (C) IfTrueNode ( iff1 ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2562 set_control( _gvn.transform( new (C) IfFalseNode( iff1 ) ) ); |
0 | 2563 |
2564 // Compile speed common case: Check for being deterministic right now. If | |
2565 // chk_off is a constant and not equal to cacheoff then we are NOT a | |
2566 // subklass. In this case we need exactly the 1 test above and we can | |
2567 // return those results immediately. | |
2568 if (!might_be_cache) { | |
2569 Node* not_subtype_ctrl = control(); | |
2570 set_control(iftrue1); // We need exactly the 1 test above | |
2571 return not_subtype_ctrl; | |
2572 } | |
2573 | |
2574 // Gather the various success & failures here | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2575 RegionNode *r_ok_subtype = new (C) RegionNode(4); |
0 | 2576 record_for_igvn(r_ok_subtype); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2577 RegionNode *r_not_subtype = new (C) RegionNode(3); |
0 | 2578 record_for_igvn(r_not_subtype); |
2579 | |
2580 r_ok_subtype->init_req(1, iftrue1); | |
2581 | |
2582 // Check for immediate negative hit. Happens roughly 11% of the time (which | |
2583 // is roughly 63% of the remaining cases). Test to see if the loaded | |
2584 // check-offset points into the subklass display list or the 1-element | |
2585 // cache. If it points to the display (and NOT the cache) and the display | |
2586 // missed then it's not a subtype. | |
2587 Node *cacheoff = _gvn.intcon(cacheoff_con); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2588 Node *cmp2 = _gvn.transform( new (C) CmpINode( chk_off, cacheoff ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2589 Node *bol2 = _gvn.transform( new (C) BoolNode( cmp2, BoolTest::ne ) ); |
0 | 2590 IfNode *iff2 = create_and_xform_if( control(), bol2, PROB_LIKELY(0.63f), COUNT_UNKNOWN ); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2591 r_not_subtype->init_req(1, _gvn.transform( new (C) IfTrueNode (iff2) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2592 set_control( _gvn.transform( new (C) IfFalseNode(iff2) ) ); |
0 | 2593 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2594 // Check for self. Very rare to get here, but it is taken 1/3 the time. |
0 | 2595 // No performance impact (too rare) but allows sharing of secondary arrays |
2596 // which has some footprint reduction. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2597 Node *cmp3 = _gvn.transform( new (C) CmpPNode( subklass, superklass ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2598 Node *bol3 = _gvn.transform( new (C) BoolNode( cmp3, BoolTest::eq ) ); |
0 | 2599 IfNode *iff3 = create_and_xform_if( control(), bol3, PROB_LIKELY(0.36f), COUNT_UNKNOWN ); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2600 r_ok_subtype->init_req(2, _gvn.transform( new (C) IfTrueNode ( iff3 ) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2601 set_control( _gvn.transform( new (C) IfFalseNode( iff3 ) ) ); |
0 | 2602 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2603 // -- Roads not taken here: -- |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2604 // We could also have chosen to perform the self-check at the beginning |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2605 // of this code sequence, as the assembler does. This would not pay off |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2606 // the same way, since the optimizer, unlike the assembler, can perform |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2607 // static type analysis to fold away many successful self-checks. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2608 // Non-foldable self checks work better here in second position, because |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2609 // the initial primary superclass check subsumes a self-check for most |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2610 // types. An exception would be a secondary type like array-of-interface, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2611 // which does not appear in its own primary supertype display. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2612 // Finally, we could have chosen to move the self-check into the |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2613 // PartialSubtypeCheckNode, and from there out-of-line in a platform |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2614 // dependent manner. But it is worthwhile to have the check here, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2615 // where it can be perhaps be optimized. The cost in code space is |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2616 // small (register compare, branch). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2617 |
0 | 2618 // Now do a linear scan of the secondary super-klass array. Again, no real |
2619 // performance impact (too rare) but it's gotta be done. | |
2620 // Since the code is rarely used, there is no penalty for moving it | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2621 // out of line, and it can only improve I-cache density. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2622 // The decision to inline or out-of-line this final check is platform |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
605
diff
changeset
|
2623 // dependent, and is found in the AD file definition of PartialSubtypeCheck. |
0 | 2624 Node* psc = _gvn.transform( |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2625 new (C) PartialSubtypeCheckNode(control(), subklass, superklass) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2626 |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2627 Node *cmp4 = _gvn.transform( new (C) CmpPNode( psc, null() ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2628 Node *bol4 = _gvn.transform( new (C) BoolNode( cmp4, BoolTest::ne ) ); |
0 | 2629 IfNode *iff4 = create_and_xform_if( control(), bol4, PROB_FAIR, COUNT_UNKNOWN ); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2630 r_not_subtype->init_req(2, _gvn.transform( new (C) IfTrueNode (iff4) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2631 r_ok_subtype ->init_req(3, _gvn.transform( new (C) IfFalseNode(iff4) ) ); |
0 | 2632 |
2633 // Return false path; set default control to true path. | |
2634 set_control( _gvn.transform(r_ok_subtype) ); | |
2635 return _gvn.transform(r_not_subtype); | |
2636 } | |
2637 | |
2638 //----------------------------static_subtype_check----------------------------- | |
2639 // Shortcut important common cases when superklass is exact: | |
2640 // (0) superklass is java.lang.Object (can occur in reflective code) | |
2641 // (1) subklass is already limited to a subtype of superklass => always ok | |
2642 // (2) subklass does not overlap with superklass => always fail | |
2643 // (3) superklass has NO subtypes and we can check with a simple compare. | |
2644 int GraphKit::static_subtype_check(ciKlass* superk, ciKlass* subk) { | |
2645 if (StressReflectiveCode) { | |
2646 return SSC_full_test; // Let caller generate the general case. | |
2647 } | |
2648 | |
2649 if (superk == env()->Object_klass()) { | |
2650 return SSC_always_true; // (0) this test cannot fail | |
2651 } | |
2652 | |
2653 ciType* superelem = superk; | |
2654 if (superelem->is_array_klass()) | |
2655 superelem = superelem->as_array_klass()->base_element_type(); | |
2656 | |
2657 if (!subk->is_interface()) { // cannot trust static interface types yet | |
2658 if (subk->is_subtype_of(superk)) { | |
2659 return SSC_always_true; // (1) false path dead; no dynamic test needed | |
2660 } | |
2661 if (!(superelem->is_klass() && superelem->as_klass()->is_interface()) && | |
2662 !superk->is_subtype_of(subk)) { | |
2663 return SSC_always_false; | |
2664 } | |
2665 } | |
2666 | |
2667 // If casting to an instance klass, it must have no subtypes | |
2668 if (superk->is_interface()) { | |
2669 // Cannot trust interfaces yet. | |
2670 // %%% S.B. superk->nof_implementors() == 1 | |
2671 } else if (superelem->is_instance_klass()) { | |
2672 ciInstanceKlass* ik = superelem->as_instance_klass(); | |
2673 if (!ik->has_subklass() && !ik->is_interface()) { | |
2674 if (!ik->is_final()) { | |
2675 // Add a dependency if there is a chance of a later subclass. | |
2676 C->dependencies()->assert_leaf_type(ik); | |
2677 } | |
2678 return SSC_easy_test; // (3) caller can do a simple ptr comparison | |
2679 } | |
2680 } else { | |
2681 // A primitive array type has no subtypes. | |
2682 return SSC_easy_test; // (3) caller can do a simple ptr comparison | |
2683 } | |
2684 | |
2685 return SSC_full_test; | |
2686 } | |
2687 | |
2688 // Profile-driven exact type check: | |
2689 Node* GraphKit::type_check_receiver(Node* receiver, ciKlass* klass, | |
2690 float prob, | |
2691 Node* *casted_receiver) { | |
2692 const TypeKlassPtr* tklass = TypeKlassPtr::make(klass); | |
2693 Node* recv_klass = load_object_klass(receiver); | |
2694 Node* want_klass = makecon(tklass); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2695 Node* cmp = _gvn.transform( new(C) CmpPNode(recv_klass, want_klass) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2696 Node* bol = _gvn.transform( new(C) BoolNode(cmp, BoolTest::eq) ); |
0 | 2697 IfNode* iff = create_and_xform_if(control(), bol, prob, COUNT_UNKNOWN); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2698 set_control( _gvn.transform( new(C) IfTrueNode (iff) )); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2699 Node* fail = _gvn.transform( new(C) IfFalseNode(iff) ); |
0 | 2700 |
2701 const TypeOopPtr* recv_xtype = tklass->as_instance_type(); | |
2702 assert(recv_xtype->klass_is_exact(), ""); | |
2703 | |
2704 // Subsume downstream occurrences of receiver with a cast to | |
2705 // recv_xtype, since now we know what the type will be. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2706 Node* cast = new(C) CheckCastPPNode(control(), receiver, recv_xtype); |
0 | 2707 (*casted_receiver) = _gvn.transform(cast); |
2708 // (User must make the replace_in_map call.) | |
2709 | |
2710 return fail; | |
2711 } | |
2712 | |
2713 | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2714 //------------------------------seems_never_null------------------------------- |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2715 // Use null_seen information if it is available from the profile. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2716 // If we see an unexpected null at a type check we record it and force a |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2717 // recompile; the offending check will be recompiled to handle NULLs. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2718 // If we see several offending BCIs, then all checks in the |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2719 // method will be recompiled. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2720 bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) { |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2721 if (UncommonNullCast // Cutout for this technique |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2722 && obj != null() // And not the -Xcomp stupid case? |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2723 && !too_many_traps(Deoptimization::Reason_null_check) |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2724 ) { |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2725 if (data == NULL) |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2726 // Edge case: no mature data. Be optimistic here. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2727 return true; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2728 // If the profile has not seen a null, assume it won't happen. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2729 assert(java_bc() == Bytecodes::_checkcast || |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2730 java_bc() == Bytecodes::_instanceof || |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2731 java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here"); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2732 return !data->as_BitData()->null_seen(); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2733 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2734 return false; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2735 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2736 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2737 //------------------------maybe_cast_profiled_receiver------------------------- |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2738 // If the profile has seen exactly one type, narrow to exactly that type. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2739 // Subsequent type checks will always fold up. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2740 Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, |
12966 | 2741 ciKlass* require_klass, |
2742 ciKlass* spec_klass, | |
2743 bool safe_for_replace) { | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2744 if (!UseTypeProfile || !TypeProfileCasts) return NULL; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2745 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2746 // Make sure we haven't already deoptimized from this tactic. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2747 if (too_many_traps(Deoptimization::Reason_class_check)) |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2748 return NULL; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2749 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2750 // (No, this isn't a call, but it's enough like a virtual call |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2751 // to use the same ciMethod accessor to get the profile info...) |
12966 | 2752 // If we have a speculative type use it instead of profiling (which |
2753 // may not help us) | |
2754 ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass; | |
2755 if (exact_kls != NULL) {// no cast failures here | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2756 if (require_klass == NULL || |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2757 static_subtype_check(require_klass, exact_kls) == SSC_always_true) { |
12966 | 2758 // If we narrow the type to match what the type profile sees or |
2759 // the speculative type, we can then remove the rest of the | |
2760 // cast. | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2761 // This is a win, even if the exact_kls is very specific, |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2762 // because downstream operations, such as method calls, |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2763 // will often benefit from the sharper type. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2764 Node* exact_obj = not_null_obj; // will get updated in place... |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2765 Node* slow_ctl = type_check_receiver(exact_obj, exact_kls, 1.0, |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2766 &exact_obj); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2767 { PreserveJVMState pjvms(this); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2768 set_control(slow_ctl); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2769 uncommon_trap(Deoptimization::Reason_class_check, |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2770 Deoptimization::Action_maybe_recompile); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2771 } |
12966 | 2772 if (safe_for_replace) { |
2773 replace_in_map(not_null_obj, exact_obj); | |
2774 } | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2775 return exact_obj; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2776 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2777 // assert(ssc == SSC_always_true)... except maybe the profile lied to us. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2778 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2779 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2780 return NULL; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2781 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2782 |
12966 | 2783 /** |
2784 * Cast obj to type and emit guard unless we had too many traps here | |
2785 * already | |
2786 * | |
2787 * @param obj node being casted | |
2788 * @param type type to cast the node to | |
2789 * @param not_null true if we know node cannot be null | |
2790 */ | |
2791 Node* GraphKit::maybe_cast_profiled_obj(Node* obj, | |
2792 ciKlass* type, | |
2793 bool not_null) { | |
2794 // type == NULL if profiling tells us this object is always null | |
2795 if (type != NULL) { | |
2796 if (!too_many_traps(Deoptimization::Reason_null_check) && | |
2797 !too_many_traps(Deoptimization::Reason_class_check)) { | |
2798 Node* not_null_obj = NULL; | |
2799 // not_null is true if we know the object is not null and | |
2800 // there's no need for a null check | |
2801 if (!not_null) { | |
2802 Node* null_ctl = top(); | |
2803 not_null_obj = null_check_oop(obj, &null_ctl, true, true); | |
2804 assert(null_ctl->is_top(), "no null control here"); | |
2805 } else { | |
2806 not_null_obj = obj; | |
2807 } | |
2808 | |
2809 Node* exact_obj = not_null_obj; | |
2810 ciKlass* exact_kls = type; | |
2811 Node* slow_ctl = type_check_receiver(exact_obj, exact_kls, 1.0, | |
2812 &exact_obj); | |
2813 { | |
2814 PreserveJVMState pjvms(this); | |
2815 set_control(slow_ctl); | |
2816 uncommon_trap(Deoptimization::Reason_class_check, | |
2817 Deoptimization::Action_maybe_recompile); | |
2818 } | |
2819 replace_in_map(not_null_obj, exact_obj); | |
2820 obj = exact_obj; | |
2821 } | |
2822 } else { | |
2823 if (!too_many_traps(Deoptimization::Reason_null_assert)) { | |
2824 Node* exact_obj = null_assert(obj); | |
2825 replace_in_map(obj, exact_obj); | |
2826 obj = exact_obj; | |
2827 } | |
2828 } | |
2829 return obj; | |
2830 } | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2831 |
0 | 2832 //-------------------------------gen_instanceof-------------------------------- |
2833 // Generate an instance-of idiom. Used by both the instance-of bytecode | |
2834 // and the reflective instance-of call. | |
12966 | 2835 Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replace) { |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2836 kill_dead_locals(); // Benefit all the uncommon traps |
0 | 2837 assert( !stopped(), "dead parse path should be checked in callers" ); |
2838 assert(!TypePtr::NULL_PTR->higher_equal(_gvn.type(superklass)->is_klassptr()), | |
2839 "must check for not-null not-dead klass in callers"); | |
2840 | |
2841 // Make the merge point | |
2842 enum { _obj_path = 1, _fail_path, _null_path, PATH_LIMIT }; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2843 RegionNode* region = new(C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2844 Node* phi = new(C) PhiNode(region, TypeInt::BOOL); |
0 | 2845 C->set_has_split_ifs(true); // Has chance for split-if optimization |
2846 | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2847 ciProfileData* data = NULL; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2848 if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2849 data = method()->method_data()->bci_to_data(bci()); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2850 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2851 bool never_see_null = (ProfileDynamicTypes // aggressive use of profile |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2852 && seems_never_null(obj, data)); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2853 |
0 | 2854 // Null check; get casted pointer; set region slot 3 |
2855 Node* null_ctl = top(); | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2856 Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace); |
0 | 2857 |
2858 // If not_null_obj is dead, only null-path is taken | |
2859 if (stopped()) { // Doing instance-of on a NULL? | |
2860 set_control(null_ctl); | |
2861 return intcon(0); | |
2862 } | |
2863 region->init_req(_null_path, null_ctl); | |
2864 phi ->init_req(_null_path, intcon(0)); // Set null path value | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2865 if (null_ctl == top()) { |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2866 // Do this eagerly, so that pattern matches like is_diamond_phi |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2867 // will work even during parsing. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2868 assert(_null_path == PATH_LIMIT-1, "delete last"); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2869 region->del_req(_null_path); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2870 phi ->del_req(_null_path); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2871 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2872 |
12966 | 2873 // Do we know the type check always succeed? |
2874 bool known_statically = false; | |
2875 if (_gvn.type(superklass)->singleton()) { | |
2876 ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); | |
2877 ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass(); | |
2878 if (subk != NULL && subk->is_loaded()) { | |
2879 int static_res = static_subtype_check(superk, subk); | |
2880 known_statically = (static_res == SSC_always_true || static_res == SSC_always_false); | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2881 } |
12966 | 2882 } |
2883 | |
2884 if (known_statically && UseTypeSpeculation) { | |
2885 // If we know the type check always succeed then we don't use the | |
2886 // profiling data at this bytecode. Don't lose it, feed it to the | |
2887 // type system as a speculative type. | |
2888 not_null_obj = record_profiled_receiver_for_speculation(not_null_obj); | |
2889 } else { | |
2890 const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr(); | |
2891 // We may not have profiling here or it may not help us. If we | |
2892 // have a speculative type use it to perform an exact cast. | |
2893 ciKlass* spec_obj_type = obj_type->speculative_type(); | |
2894 if (spec_obj_type != NULL || (ProfileDynamicTypes && data != NULL)) { | |
2895 Node* cast_obj = maybe_cast_profiled_receiver(not_null_obj, NULL, spec_obj_type, safe_for_replace); | |
2896 if (stopped()) { // Profile disagrees with this path. | |
2897 set_control(null_ctl); // Null is the only remaining possibility. | |
2898 return intcon(0); | |
2899 } | |
2900 if (cast_obj != NULL) { | |
2901 not_null_obj = cast_obj; | |
2902 } | |
2903 } | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2904 } |
0 | 2905 |
2906 // Load the object's klass | |
2907 Node* obj_klass = load_object_klass(not_null_obj); | |
2908 | |
2909 // Generate the subtype check | |
2910 Node* not_subtype_ctrl = gen_subtype_check(obj_klass, superklass); | |
2911 | |
2912 // Plug in the success path to the general merge in slot 1. | |
2913 region->init_req(_obj_path, control()); | |
2914 phi ->init_req(_obj_path, intcon(1)); | |
2915 | |
2916 // Plug in the failing path to the general merge in slot 2. | |
2917 region->init_req(_fail_path, not_subtype_ctrl); | |
2918 phi ->init_req(_fail_path, intcon(0)); | |
2919 | |
2920 // Return final merged results | |
2921 set_control( _gvn.transform(region) ); | |
2922 record_for_igvn(region); | |
2923 return _gvn.transform(phi); | |
2924 } | |
2925 | |
2926 //-------------------------------gen_checkcast--------------------------------- | |
2927 // Generate a checkcast idiom. Used by both the checkcast bytecode and the | |
2928 // array store bytecode. Stack must be as-if BEFORE doing the bytecode so the | |
2929 // uncommon-trap paths work. Adjust stack after this call. | |
2930 // If failure_control is supplied and not null, it is filled in with | |
2931 // the control edge for the cast failure. Otherwise, an appropriate | |
2932 // uncommon trap or exception is thrown. | |
2933 Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, | |
2934 Node* *failure_control) { | |
2935 kill_dead_locals(); // Benefit all the uncommon traps | |
2936 const TypeKlassPtr *tk = _gvn.type(superklass)->is_klassptr(); | |
2937 const Type *toop = TypeOopPtr::make_from_klass(tk->klass()); | |
2938 | |
2939 // Fast cutout: Check the case that the cast is vacuously true. | |
2940 // This detects the common cases where the test will short-circuit | |
2941 // away completely. We do this before we perform the null check, | |
2942 // because if the test is going to turn into zero code, we don't | |
2943 // want a residual null check left around. (Causes a slowdown, | |
2944 // for example, in some objArray manipulations, such as a[i]=a[j].) | |
2945 if (tk->singleton()) { | |
2946 const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr(); | |
2947 if (objtp != NULL && objtp->klass() != NULL) { | |
2948 switch (static_subtype_check(tk->klass(), objtp->klass())) { | |
2949 case SSC_always_true: | |
12966 | 2950 // If we know the type check always succeed then we don't use |
2951 // the profiling data at this bytecode. Don't lose it, feed it | |
2952 // to the type system as a speculative type. | |
2953 return record_profiled_receiver_for_speculation(obj); | |
0 | 2954 case SSC_always_false: |
2955 // It needs a null check because a null will *pass* the cast check. | |
2956 // A non-null value will always produce an exception. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
2957 return null_assert(obj); |
0 | 2958 } |
2959 } | |
2960 } | |
2961 | |
2962 ciProfileData* data = NULL; | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2963 bool safe_for_replace = false; |
0 | 2964 if (failure_control == NULL) { // use MDO in regular case only |
2965 assert(java_bc() == Bytecodes::_aastore || | |
2966 java_bc() == Bytecodes::_checkcast, | |
2967 "interpreter profiles type checks only for these BCs"); | |
2968 data = method()->method_data()->bci_to_data(bci()); | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2969 safe_for_replace = true; |
0 | 2970 } |
2971 | |
2972 // Make the merge point | |
2973 enum { _obj_path = 1, _null_path, PATH_LIMIT }; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2974 RegionNode* region = new (C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
2975 Node* phi = new (C) PhiNode(region, toop); |
0 | 2976 C->set_has_split_ifs(true); // Has chance for split-if optimization |
2977 | |
2978 // Use null-cast information if it is available | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2979 bool never_see_null = ((failure_control == NULL) // regular case only |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2980 && seems_never_null(obj, data)); |
0 | 2981 |
2982 // Null check; get casted pointer; set region slot 3 | |
2983 Node* null_ctl = top(); | |
12869
d9043b88eeb3
8024067: Missing replace_in_map() calls following null checks
roland
parents:
12331
diff
changeset
|
2984 Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace); |
0 | 2985 |
2986 // If not_null_obj is dead, only null-path is taken | |
2987 if (stopped()) { // Doing instance-of on a NULL? | |
2988 set_control(null_ctl); | |
2989 return null(); | |
2990 } | |
2991 region->init_req(_null_path, null_ctl); | |
2992 phi ->init_req(_null_path, null()); // Set null path value | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2993 if (null_ctl == top()) { |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2994 // Do this eagerly, so that pattern matches like is_diamond_phi |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2995 // will work even during parsing. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2996 assert(_null_path == PATH_LIMIT-1, "delete last"); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2997 region->del_req(_null_path); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2998 phi ->del_req(_null_path); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
2999 } |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3000 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3001 Node* cast_obj = NULL; |
12966 | 3002 const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr(); |
3003 // We may not have profiling here or it may not help us. If we have | |
3004 // a speculative type use it to perform an exact cast. | |
3005 ciKlass* spec_obj_type = obj_type->speculative_type(); | |
3006 if (spec_obj_type != NULL || | |
3007 (data != NULL && | |
3008 // Counter has never been decremented (due to cast failure). | |
3009 // ...This is a reasonable thing to expect. It is true of | |
3010 // all casts inserted by javac to implement generic types. | |
3011 data->as_CounterData()->count() >= 0)) { | |
3012 cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace); | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3013 if (cast_obj != NULL) { |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3014 if (failure_control != NULL) // failure is now impossible |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3015 (*failure_control) = top(); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3016 // adjust the type of the phi to the exact klass: |
14383
5ec7dace41a6
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
14223
diff
changeset
|
3017 phi->raise_bottom_type(_gvn.type(cast_obj)->meet_speculative(TypePtr::NULL_PTR)); |
0 | 3018 } |
3019 } | |
3020 | |
3021 if (cast_obj == NULL) { | |
3022 // Load the object's klass | |
3023 Node* obj_klass = load_object_klass(not_null_obj); | |
3024 | |
3025 // Generate the subtype check | |
3026 Node* not_subtype_ctrl = gen_subtype_check( obj_klass, superklass ); | |
3027 | |
3028 // Plug in success path into the merge | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3029 cast_obj = _gvn.transform(new (C) CheckCastPPNode(control(), |
0 | 3030 not_null_obj, toop)); |
3031 // Failure path ends in uncommon trap (or may be dead - failure impossible) | |
3032 if (failure_control == NULL) { | |
3033 if (not_subtype_ctrl != top()) { // If failure is possible | |
3034 PreserveJVMState pjvms(this); | |
3035 set_control(not_subtype_ctrl); | |
3036 builtin_throw(Deoptimization::Reason_class_check, obj_klass); | |
3037 } | |
3038 } else { | |
3039 (*failure_control) = not_subtype_ctrl; | |
3040 } | |
3041 } | |
3042 | |
3043 region->init_req(_obj_path, control()); | |
3044 phi ->init_req(_obj_path, cast_obj); | |
3045 | |
3046 // A merge of NULL or Casted-NotNull obj | |
3047 Node* res = _gvn.transform(phi); | |
3048 | |
3049 // Note I do NOT always 'replace_in_map(obj,result)' here. | |
3050 // if( tk->klass()->can_be_primary_super() ) | |
3051 // This means that if I successfully store an Object into an array-of-String | |
3052 // I 'forget' that the Object is really now known to be a String. I have to | |
3053 // do this because we don't have true union types for interfaces - if I store | |
3054 // a Baz into an array-of-Interface and then tell the optimizer it's an | |
3055 // Interface, I forget that it's also a Baz and cannot do Baz-like field | |
3056 // references to it. FIX THIS WHEN UNION TYPES APPEAR! | |
3057 // replace_in_map( obj, res ); | |
3058 | |
3059 // Return final merged results | |
3060 set_control( _gvn.transform(region) ); | |
3061 record_for_igvn(region); | |
3062 return res; | |
3063 } | |
3064 | |
3065 //------------------------------next_monitor----------------------------------- | |
3066 // What number should be given to the next monitor? | |
3067 int GraphKit::next_monitor() { | |
3068 int current = jvms()->monitor_depth()* C->sync_stack_slots(); | |
3069 int next = current + C->sync_stack_slots(); | |
3070 // Keep the toplevel high water mark current: | |
3071 if (C->fixed_slots() < next) C->set_fixed_slots(next); | |
3072 return current; | |
3073 } | |
3074 | |
3075 //------------------------------insert_mem_bar--------------------------------- | |
3076 // Memory barrier to avoid floating things around | |
3077 // The membar serves as a pinch point between both control and all memory slices. | |
3078 Node* GraphKit::insert_mem_bar(int opcode, Node* precedent) { | |
3079 MemBarNode* mb = MemBarNode::make(C, opcode, Compile::AliasIdxBot, precedent); | |
3080 mb->init_req(TypeFunc::Control, control()); | |
3081 mb->init_req(TypeFunc::Memory, reset_memory()); | |
3082 Node* membar = _gvn.transform(mb); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
3083 set_control(_gvn.transform(new (C) ProjNode(membar, TypeFunc::Control))); |
0 | 3084 set_all_memory_call(membar); |
3085 return membar; | |
3086 } | |
3087 | |
3088 //-------------------------insert_mem_bar_volatile---------------------------- | |
3089 // Memory barrier to avoid floating things around | |
3090 // The membar serves as a pinch point between both control and memory(alias_idx). | |
3091 // If you want to make a pinch point on all memory slices, do not use this | |
3092 // function (even with AliasIdxBot); use insert_mem_bar() instead. | |
3093 Node* GraphKit::insert_mem_bar_volatile(int opcode, int alias_idx, Node* precedent) { | |
3094 // When Parse::do_put_xxx updates a volatile field, it appends a series | |
3095 // of MemBarVolatile nodes, one for *each* volatile field alias category. | |
3096 // The first membar is on the same memory slice as the field store opcode. | |
3097 // This forces the membar to follow the store. (Bug 6500685 broke this.) | |
3098 // All the other membars (for other volatile slices, including AliasIdxBot, | |
3099 // which stands for all unknown volatile slices) are control-dependent | |
3100 // on the first membar. This prevents later volatile loads or stores | |
3101 // from sliding up past the just-emitted store. | |
3102 | |
3103 MemBarNode* mb = MemBarNode::make(C, opcode, alias_idx, precedent); | |
3104 mb->set_req(TypeFunc::Control,control()); | |
3105 if (alias_idx == Compile::AliasIdxBot) { | |
3106 mb->set_req(TypeFunc::Memory, merged_memory()->base_memory()); | |
3107 } else { | |
3108 assert(!(opcode == Op_Initialize && alias_idx != Compile::AliasIdxRaw), "fix caller"); | |
3109 mb->set_req(TypeFunc::Memory, memory(alias_idx)); | |
3110 } | |
3111 Node* membar = _gvn.transform(mb); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3112 set_control(_gvn.transform(new (C) ProjNode(membar, TypeFunc::Control))); |
0 | 3113 if (alias_idx == Compile::AliasIdxBot) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3114 merged_memory()->set_base_memory(_gvn.transform(new (C) ProjNode(membar, TypeFunc::Memory))); |
0 | 3115 } else { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3116 set_memory(_gvn.transform(new (C) ProjNode(membar, TypeFunc::Memory)),alias_idx); |
0 | 3117 } |
3118 return membar; | |
3119 } | |
3120 | |
3121 //------------------------------shared_lock------------------------------------ | |
3122 // Emit locking code. | |
3123 FastLockNode* GraphKit::shared_lock(Node* obj) { | |
3124 // bci is either a monitorenter bc or InvocationEntryBci | |
3125 // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces | |
3126 assert(SynchronizationEntryBCI == InvocationEntryBci, ""); | |
3127 | |
3128 if( !GenerateSynchronizationCode ) | |
3129 return NULL; // Not locking things? | |
3130 if (stopped()) // Dead monitor? | |
3131 return NULL; | |
3132 | |
3133 assert(dead_locals_are_killed(), "should kill locals before sync. point"); | |
3134 | |
3135 // Box the stack location | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3136 Node* box = _gvn.transform(new (C) BoxLockNode(next_monitor())); |
0 | 3137 Node* mem = reset_memory(); |
3138 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3139 FastLockNode * flock = _gvn.transform(new (C) FastLockNode(0, obj, box) )->as_FastLock(); |
0 | 3140 if (PrintPreciseBiasedLockingStatistics) { |
3141 // Create the counters for this fast lock. | |
3142 flock->create_lock_counter(sync_jvms()); // sync_jvms used to get current bci | |
3143 } | |
3144 // Add monitor to debug info for the slow path. If we block inside the | |
3145 // slow path and de-opt, we need the monitor hanging around | |
3146 map()->push_monitor( flock ); | |
3147 | |
3148 const TypeFunc *tf = LockNode::lock_type(); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3149 LockNode *lock = new (C) LockNode(C, tf); |
0 | 3150 |
3151 lock->init_req( TypeFunc::Control, control() ); | |
3152 lock->init_req( TypeFunc::Memory , mem ); | |
3153 lock->init_req( TypeFunc::I_O , top() ) ; // does no i/o | |
3154 lock->init_req( TypeFunc::FramePtr, frameptr() ); | |
3155 lock->init_req( TypeFunc::ReturnAdr, top() ); | |
3156 | |
3157 lock->init_req(TypeFunc::Parms + 0, obj); | |
3158 lock->init_req(TypeFunc::Parms + 1, box); | |
3159 lock->init_req(TypeFunc::Parms + 2, flock); | |
3160 add_safepoint_edges(lock); | |
3161 | |
3162 lock = _gvn.transform( lock )->as_Lock(); | |
3163 | |
3164 // lock has no side-effects, sets few values | |
3165 set_predefined_output_for_runtime_call(lock, mem, TypeRawPtr::BOTTOM); | |
3166 | |
3849
f1c12354c3f7
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
3345
diff
changeset
|
3167 insert_mem_bar(Op_MemBarAcquireLock); |
0 | 3168 |
3169 // Add this to the worklist so that the lock can be eliminated | |
3170 record_for_igvn(lock); | |
3171 | |
3172 #ifndef PRODUCT | |
3173 if (PrintLockStatistics) { | |
3174 // Update the counter for this lock. Don't bother using an atomic | |
3175 // operation since we don't require absolute accuracy. | |
3176 lock->create_lock_counter(map()->jvms()); | |
1609 | 3177 increment_counter(lock->counter()->addr()); |
0 | 3178 } |
3179 #endif | |
3180 | |
3181 return flock; | |
3182 } | |
3183 | |
3184 | |
3185 //------------------------------shared_unlock---------------------------------- | |
3186 // Emit unlocking code. | |
3187 void GraphKit::shared_unlock(Node* box, Node* obj) { | |
3188 // bci is either a monitorenter bc or InvocationEntryBci | |
3189 // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces | |
3190 assert(SynchronizationEntryBCI == InvocationEntryBci, ""); | |
3191 | |
3192 if( !GenerateSynchronizationCode ) | |
3193 return; | |
3194 if (stopped()) { // Dead monitor? | |
3195 map()->pop_monitor(); // Kill monitor from debug info | |
3196 return; | |
3197 } | |
3198 | |
3199 // Memory barrier to avoid floating things down past the locked region | |
3849
f1c12354c3f7
7074017: Introduce MemBarAcquireLock/MemBarReleaseLock nodes for monitor enter/exit code paths
roland
parents:
3345
diff
changeset
|
3200 insert_mem_bar(Op_MemBarReleaseLock); |
0 | 3201 |
3202 const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type(); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3203 UnlockNode *unlock = new (C) UnlockNode(C, tf); |
0 | 3204 uint raw_idx = Compile::AliasIdxRaw; |
3205 unlock->init_req( TypeFunc::Control, control() ); | |
3206 unlock->init_req( TypeFunc::Memory , memory(raw_idx) ); | |
3207 unlock->init_req( TypeFunc::I_O , top() ) ; // does no i/o | |
3208 unlock->init_req( TypeFunc::FramePtr, frameptr() ); | |
3209 unlock->init_req( TypeFunc::ReturnAdr, top() ); | |
3210 | |
3211 unlock->init_req(TypeFunc::Parms + 0, obj); | |
3212 unlock->init_req(TypeFunc::Parms + 1, box); | |
3213 unlock = _gvn.transform(unlock)->as_Unlock(); | |
3214 | |
3215 Node* mem = reset_memory(); | |
3216 | |
3217 // unlock has no side-effects, sets few values | |
3218 set_predefined_output_for_runtime_call(unlock, mem, TypeRawPtr::BOTTOM); | |
3219 | |
3220 // Kill monitor from debug info | |
3221 map()->pop_monitor( ); | |
3222 } | |
3223 | |
3224 //-------------------------------get_layout_helper----------------------------- | |
3225 // If the given klass is a constant or known to be an array, | |
3226 // fetch the constant layout helper value into constant_value | |
3227 // and return (Node*)NULL. Otherwise, load the non-constant | |
3228 // layout helper value, and return the node which represents it. | |
3229 // This two-faced routine is useful because allocation sites | |
3230 // almost always feature constant types. | |
3231 Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) { | |
3232 const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr(); | |
3233 if (!StressReflectiveCode && inst_klass != NULL) { | |
3234 ciKlass* klass = inst_klass->klass(); | |
3235 bool xklass = inst_klass->klass_is_exact(); | |
3236 if (xklass || klass->is_array_klass()) { | |
3237 jint lhelper = klass->layout_helper(); | |
3238 if (lhelper != Klass::_lh_neutral_value) { | |
3239 constant_value = lhelper; | |
3240 return (Node*) NULL; | |
3241 } | |
3242 } | |
3243 } | |
3244 constant_value = Klass::_lh_neutral_value; // put in a known value | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3849
diff
changeset
|
3245 Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3246 return make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered); |
0 | 3247 } |
3248 | |
3249 // We just put in an allocate/initialize with a big raw-memory effect. | |
3250 // Hook selected additional alias categories on the initialization. | |
3251 static void hook_memory_on_init(GraphKit& kit, int alias_idx, | |
3252 MergeMemNode* init_in_merge, | |
3253 Node* init_out_raw) { | |
3254 DEBUG_ONLY(Node* init_in_raw = init_in_merge->base_memory()); | |
3255 assert(init_in_merge->memory_at(alias_idx) == init_in_raw, ""); | |
3256 | |
3257 Node* prevmem = kit.memory(alias_idx); | |
3258 init_in_merge->set_memory_at(alias_idx, prevmem); | |
3259 kit.set_memory(init_out_raw, alias_idx); | |
3260 } | |
3261 | |
3262 //---------------------------set_output_for_allocation------------------------- | |
3263 Node* GraphKit::set_output_for_allocation(AllocateNode* alloc, | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2468
diff
changeset
|
3264 const TypeOopPtr* oop_type) { |
0 | 3265 int rawidx = Compile::AliasIdxRaw; |
3266 alloc->set_req( TypeFunc::FramePtr, frameptr() ); | |
3267 add_safepoint_edges(alloc); | |
3268 Node* allocx = _gvn.transform(alloc); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3269 set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) ); |
0 | 3270 // create memory projection for i_o |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3271 set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx ); |
7428
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
7421
diff
changeset
|
3272 make_slow_call_ex(allocx, env()->Throwable_klass(), true); |
0 | 3273 |
3274 // create a memory projection as for the normal control path | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3275 Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory)); |
0 | 3276 set_memory(malloc, rawidx); |
3277 | |
3278 // a normal slow-call doesn't change i_o, but an allocation does | |
3279 // we create a separate i_o projection for the normal control path | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3280 set_i_o(_gvn.transform( new (C) ProjNode(allocx, TypeFunc::I_O, false) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3281 Node* rawoop = _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Parms) ); |
0 | 3282 |
3283 // put in an initialization barrier | |
3284 InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, rawidx, | |
3285 rawoop)->as_Initialize(); | |
3286 assert(alloc->initialization() == init, "2-way macro link must work"); | |
3287 assert(init ->allocation() == alloc, "2-way macro link must work"); | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2468
diff
changeset
|
3288 { |
0 | 3289 // Extract memory strands which may participate in the new object's |
3290 // initialization, and source them from the new InitializeNode. | |
3291 // This will allow us to observe initializations when they occur, | |
3292 // and link them properly (as a group) to the InitializeNode. | |
3293 assert(init->in(InitializeNode::Memory) == malloc, ""); | |
3294 MergeMemNode* minit_in = MergeMemNode::make(C, malloc); | |
3295 init->set_req(InitializeNode::Memory, minit_in); | |
3296 record_for_igvn(minit_in); // fold it up later, if possible | |
3297 Node* minit_out = memory(rawidx); | |
3298 assert(minit_out->is_Proj() && minit_out->in(0) == init, ""); | |
3299 if (oop_type->isa_aryptr()) { | |
3300 const TypePtr* telemref = oop_type->add_offset(Type::OffsetBot); | |
3301 int elemidx = C->get_alias_index(telemref); | |
3302 hook_memory_on_init(*this, elemidx, minit_in, minit_out); | |
3303 } else if (oop_type->isa_instptr()) { | |
3304 ciInstanceKlass* ik = oop_type->klass()->as_instance_klass(); | |
3305 for (int i = 0, len = ik->nof_nonstatic_fields(); i < len; i++) { | |
3306 ciField* field = ik->nonstatic_field_at(i); | |
23
9bdad1bb1c31
6621098: "* HeapWordSize" for TrackedInitializationLimit is missing
kvn
parents:
0
diff
changeset
|
3307 if (field->offset() >= TrackedInitializationLimit * HeapWordSize) |
0 | 3308 continue; // do not bother to track really large numbers of fields |
3309 // Find (or create) the alias category for this field: | |
3310 int fieldidx = C->alias_type(field)->index(); | |
3311 hook_memory_on_init(*this, fieldidx, minit_in, minit_out); | |
3312 } | |
3313 } | |
3314 } | |
3315 | |
3316 // Cast raw oop to the real thing... | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3317 Node* javaoop = new (C) CheckCastPPNode(control(), rawoop, oop_type); |
0 | 3318 javaoop = _gvn.transform(javaoop); |
3319 C->set_recent_alloc(control(), javaoop); | |
3320 assert(just_allocated_object(control()) == javaoop, "just allocated"); | |
3321 | |
3322 #ifdef ASSERT | |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3323 { // Verify that the AllocateNode::Ideal_allocation recognizers work: |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3324 assert(AllocateNode::Ideal_allocation(rawoop, &_gvn) == alloc, |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3325 "Ideal_allocation works"); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3326 assert(AllocateNode::Ideal_allocation(javaoop, &_gvn) == alloc, |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3327 "Ideal_allocation works"); |
0 | 3328 if (alloc->is_AllocateArray()) { |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3329 assert(AllocateArrayNode::Ideal_array_allocation(rawoop, &_gvn) == alloc->as_AllocateArray(), |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3330 "Ideal_allocation works"); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3331 assert(AllocateArrayNode::Ideal_array_allocation(javaoop, &_gvn) == alloc->as_AllocateArray(), |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3332 "Ideal_allocation works"); |
0 | 3333 } else { |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3334 assert(alloc->in(AllocateNode::ALength)->is_top(), "no length, please"); |
0 | 3335 } |
3336 } | |
3337 #endif //ASSERT | |
3338 | |
3339 return javaoop; | |
3340 } | |
3341 | |
3342 //---------------------------new_instance-------------------------------------- | |
3343 // This routine takes a klass_node which may be constant (for a static type) | |
3344 // or may be non-constant (for reflective code). It will work equally well | |
3345 // for either, and the graph will fold nicely if the optimizer later reduces | |
3346 // the type to a constant. | |
3347 // The optional arguments are for specialized use by intrinsics: | |
3348 // - If 'extra_slow_test' if not null is an extra condition for the slow-path. | |
3349 // - If 'return_size_val', report the the total object size to the caller. | |
3350 Node* GraphKit::new_instance(Node* klass_node, | |
3351 Node* extra_slow_test, | |
3352 Node* *return_size_val) { | |
3353 // Compute size in doublewords | |
3354 // The size is always an integral number of doublewords, represented | |
3355 // as a positive bytewise size stored in the klass's layout_helper. | |
3356 // The layout_helper also encodes (in a low bit) the need for a slow path. | |
3357 jint layout_con = Klass::_lh_neutral_value; | |
3358 Node* layout_val = get_layout_helper(klass_node, layout_con); | |
3359 int layout_is_con = (layout_val == NULL); | |
3360 | |
3361 if (extra_slow_test == NULL) extra_slow_test = intcon(0); | |
3362 // Generate the initial go-slow test. It's either ALWAYS (return a | |
3363 // Node for 1) or NEVER (return a NULL) or perhaps (in the reflective | |
3364 // case) a computed value derived from the layout_helper. | |
3365 Node* initial_slow_test = NULL; | |
3366 if (layout_is_con) { | |
3367 assert(!StressReflectiveCode, "stress mode does not use these paths"); | |
3368 bool must_go_slow = Klass::layout_helper_needs_slow_path(layout_con); | |
3369 initial_slow_test = must_go_slow? intcon(1): extra_slow_test; | |
3370 | |
3371 } else { // reflective case | |
3372 // This reflective path is used by Unsafe.allocateInstance. | |
3373 // (It may be stress-tested by specifying StressReflectiveCode.) | |
3374 // Basically, we want to get into the VM is there's an illegal argument. | |
3375 Node* bit = intcon(Klass::_lh_instance_slow_path_bit); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3376 initial_slow_test = _gvn.transform( new (C) AndINode(layout_val, bit) ); |
0 | 3377 if (extra_slow_test != intcon(0)) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3378 initial_slow_test = _gvn.transform( new (C) OrINode(initial_slow_test, extra_slow_test) ); |
0 | 3379 } |
3380 // (Macro-expander will further convert this to a Bool, if necessary.) | |
3381 } | |
3382 | |
3383 // Find the size in bytes. This is easy; it's the layout_helper. | |
3384 // The size value must be valid even if the slow path is taken. | |
3385 Node* size = NULL; | |
3386 if (layout_is_con) { | |
3387 size = MakeConX(Klass::layout_helper_size_in_bytes(layout_con)); | |
3388 } else { // reflective case | |
3389 // This reflective path is used by clone and Unsafe.allocateInstance. | |
3390 size = ConvI2X(layout_val); | |
3391 | |
3392 // Clear the low bits to extract layout_helper_size_in_bytes: | |
3393 assert((int)Klass::_lh_instance_slow_path_bit < BytesPerLong, "clear bit"); | |
3394 Node* mask = MakeConX(~ (intptr_t)right_n_bits(LogBytesPerLong)); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3395 size = _gvn.transform( new (C) AndXNode(size, mask) ); |
0 | 3396 } |
3397 if (return_size_val != NULL) { | |
3398 (*return_size_val) = size; | |
3399 } | |
3400 | |
3401 // This is a precise notnull oop of the klass. | |
3402 // (Actually, it need not be precise if this is a reflective allocation.) | |
3403 // It's what we cast the result to. | |
3404 const TypeKlassPtr* tklass = _gvn.type(klass_node)->isa_klassptr(); | |
3405 if (!tklass) tklass = TypeKlassPtr::OBJECT; | |
3406 const TypeOopPtr* oop_type = tklass->as_instance_type(); | |
3407 | |
3408 // Now generate allocation code | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
63
diff
changeset
|
3409 |
565
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3410 // The entire memory state is needed for slow path of the allocation |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3411 // since GC and deoptimization can happened. |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3412 Node *mem = reset_memory(); |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3413 set_all_memory(mem); // Create new memory state |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
63
diff
changeset
|
3414 |
0 | 3415 AllocateNode* alloc |
10278 | 3416 = new (C) AllocateNode(C, AllocateNode::alloc_type(Type::TOP), |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3417 control(), mem, i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3418 size, klass_node, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3419 initial_slow_test); |
0 | 3420 |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2468
diff
changeset
|
3421 return set_output_for_allocation(alloc, oop_type); |
0 | 3422 } |
3423 | |
3424 //-------------------------------new_array------------------------------------- | |
3425 // helper for both newarray and anewarray | |
3426 // The 'length' parameter is (obviously) the length of the array. | |
3427 // See comments on new_instance for the meaning of the other arguments. | |
3428 Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) | |
3429 Node* length, // number of array elements | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
726
diff
changeset
|
3430 int nargs, // number of arguments to push back for uncommon trap |
0 | 3431 Node* *return_size_val) { |
3432 jint layout_con = Klass::_lh_neutral_value; | |
3433 Node* layout_val = get_layout_helper(klass_node, layout_con); | |
3434 int layout_is_con = (layout_val == NULL); | |
3435 | |
3436 if (!layout_is_con && !StressReflectiveCode && | |
3437 !too_many_traps(Deoptimization::Reason_class_check)) { | |
3438 // This is a reflective array creation site. | |
3439 // Optimistically assume that it is a subtype of Object[], | |
3440 // so that we can fold up all the address arithmetic. | |
3441 layout_con = Klass::array_layout_helper(T_OBJECT); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3442 Node* cmp_lh = _gvn.transform( new(C) CmpINode(layout_val, intcon(layout_con)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3443 Node* bol_lh = _gvn.transform( new(C) BoolNode(cmp_lh, BoolTest::eq) ); |
0 | 3444 { BuildCutout unless(this, bol_lh, PROB_MAX); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
3445 inc_sp(nargs); |
0 | 3446 uncommon_trap(Deoptimization::Reason_class_check, |
3447 Deoptimization::Action_maybe_recompile); | |
3448 } | |
3449 layout_val = NULL; | |
3450 layout_is_con = true; | |
3451 } | |
3452 | |
3453 // Generate the initial go-slow test. Make sure we do not overflow | |
3454 // if length is huge (near 2Gig) or negative! We do not need | |
3455 // exact double-words here, just a close approximation of needed | |
3456 // double-words. We can't add any offset or rounding bits, lest we | |
3457 // take a size -1 of bytes and make it positive. Use an unsigned | |
3458 // compare, so negative sizes look hugely positive. | |
3459 int fast_size_limit = FastAllocateSizeLimit; | |
3460 if (layout_is_con) { | |
3461 assert(!StressReflectiveCode, "stress mode does not use these paths"); | |
3462 // Increase the size limit if we have exact knowledge of array type. | |
3463 int log2_esize = Klass::layout_helper_log2_element_size(layout_con); | |
3464 fast_size_limit <<= (LogBytesPerLong - log2_esize); | |
3465 } | |
3466 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3467 Node* initial_slow_cmp = _gvn.transform( new (C) CmpUNode( length, intcon( fast_size_limit ) ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3468 Node* initial_slow_test = _gvn.transform( new (C) BoolNode( initial_slow_cmp, BoolTest::gt ) ); |
0 | 3469 if (initial_slow_test->is_Bool()) { |
3470 // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick. | |
3471 initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); | |
3472 } | |
3473 | |
3474 // --- Size Computation --- | |
3475 // array_size = round_to_heap(array_header + (length << elem_shift)); | |
3476 // where round_to_heap(x) == round_to(x, MinObjAlignmentInBytes) | |
3477 // and round_to(x, y) == ((x + y-1) & ~(y-1)) | |
3478 // The rounding mask is strength-reduced, if possible. | |
3479 int round_mask = MinObjAlignmentInBytes - 1; | |
3480 Node* header_size = NULL; | |
3481 int header_size_min = arrayOopDesc::base_offset_in_bytes(T_BYTE); | |
3482 // (T_BYTE has the weakest alignment and size restrictions...) | |
3483 if (layout_is_con) { | |
3484 int hsize = Klass::layout_helper_header_size(layout_con); | |
3485 int eshift = Klass::layout_helper_log2_element_size(layout_con); | |
3486 BasicType etype = Klass::layout_helper_element_type(layout_con); | |
3487 if ((round_mask & ~right_n_bits(eshift)) == 0) | |
3488 round_mask = 0; // strength-reduce it if it goes away completely | |
3489 assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded"); | |
3490 assert(header_size_min <= hsize, "generic minimum is smallest"); | |
3491 header_size_min = hsize; | |
3492 header_size = intcon(hsize + round_mask); | |
3493 } else { | |
3494 Node* hss = intcon(Klass::_lh_header_size_shift); | |
3495 Node* hsm = intcon(Klass::_lh_header_size_mask); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3496 Node* hsize = _gvn.transform( new(C) URShiftINode(layout_val, hss) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3497 hsize = _gvn.transform( new(C) AndINode(hsize, hsm) ); |
0 | 3498 Node* mask = intcon(round_mask); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3499 header_size = _gvn.transform( new(C) AddINode(hsize, mask) ); |
0 | 3500 } |
3501 | |
3502 Node* elem_shift = NULL; | |
3503 if (layout_is_con) { | |
3504 int eshift = Klass::layout_helper_log2_element_size(layout_con); | |
3505 if (eshift != 0) | |
3506 elem_shift = intcon(eshift); | |
3507 } else { | |
3508 // There is no need to mask or shift this value. | |
3509 // The semantics of LShiftINode include an implicit mask to 0x1F. | |
3510 assert(Klass::_lh_log2_element_size_shift == 0, "use shift in place"); | |
3511 elem_shift = layout_val; | |
3512 } | |
3513 | |
3514 // Transition to native address size for all offset calculations: | |
3515 Node* lengthx = ConvI2X(length); | |
3516 Node* headerx = ConvI2X(header_size); | |
3517 #ifdef _LP64 | |
3518 { const TypeLong* tllen = _gvn.find_long_type(lengthx); | |
3519 if (tllen != NULL && tllen->_lo < 0) { | |
3520 // Add a manual constraint to a positive range. Cf. array_element_address. | |
3521 jlong size_max = arrayOopDesc::max_array_length(T_BYTE); | |
3522 if (size_max > tllen->_hi) size_max = tllen->_hi; | |
3523 const TypeLong* tlcon = TypeLong::make(CONST64(0), size_max, Type::WidenMin); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3524 lengthx = _gvn.transform( new (C) ConvI2LNode(length, tlcon)); |
0 | 3525 } |
3526 } | |
3527 #endif | |
3528 | |
3529 // Combine header size (plus rounding) and body size. Then round down. | |
3530 // This computation cannot overflow, because it is used only in two | |
3531 // places, one where the length is sharply limited, and the other | |
3532 // after a successful allocation. | |
3533 Node* abody = lengthx; | |
3534 if (elem_shift != NULL) | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3535 abody = _gvn.transform( new(C) LShiftXNode(lengthx, elem_shift) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3536 Node* size = _gvn.transform( new(C) AddXNode(headerx, abody) ); |
0 | 3537 if (round_mask != 0) { |
3538 Node* mask = MakeConX(~round_mask); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3539 size = _gvn.transform( new(C) AndXNode(size, mask) ); |
0 | 3540 } |
3541 // else if round_mask == 0, the size computation is self-rounding | |
3542 | |
3543 if (return_size_val != NULL) { | |
3544 // This is the size | |
3545 (*return_size_val) = size; | |
3546 } | |
3547 | |
3548 // Now generate allocation code | |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
63
diff
changeset
|
3549 |
565
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3550 // The entire memory state is needed for slow path of the allocation |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3551 // since GC and deoptimization can happened. |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3552 Node *mem = reset_memory(); |
7fe62bb75bf4
6799693: Server compiler leads to data corruption when expression throws an Exception
kvn
parents:
563
diff
changeset
|
3553 set_all_memory(mem); // Create new memory state |
74
2a9af0b9cb1c
6674600: (Escape Analysis) Optimize memory graph for instance's fields
kvn
parents:
63
diff
changeset
|
3554 |
0 | 3555 // Create the AllocateArrayNode and its result projections |
3556 AllocateArrayNode* alloc | |
10278 | 3557 = new (C) AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT), |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3558 control(), mem, i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3559 size, klass_node, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3560 initial_slow_test, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3561 length); |
0 | 3562 |
3563 // Cast to correct type. Note that the klass_node may be constant or not, | |
3564 // and in the latter case the actual array type will be inexact also. | |
3565 // (This happens via a non-constant argument to inline_native_newArray.) | |
3566 // In any case, the value of klass_node provides the desired array type. | |
3567 const TypeInt* length_type = _gvn.find_int_type(length); | |
3568 const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); | |
3569 if (ary_type->isa_aryptr() && length_type != NULL) { | |
3570 // Try to get a better type than POS for the size | |
3571 ary_type = ary_type->is_aryptr()->cast_to_size(length_type); | |
3572 } | |
3573 | |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2468
diff
changeset
|
3574 Node* javaoop = set_output_for_allocation(alloc, ary_type); |
0 | 3575 |
366
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3576 // Cast length on remaining path to be as narrow as possible |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3577 if (map()->find_edge(length) >= 0) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3578 Node* ccast = alloc->make_ideal_length(ary_type, &_gvn); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3579 if (ccast != length) { |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3580 _gvn.set_type_bottom(ccast); |
8261ee795323
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
rasbold
parents:
332
diff
changeset
|
3581 record_for_igvn(ccast); |
0 | 3582 replace_in_map(length, ccast); |
3583 } | |
3584 } | |
3585 | |
3586 return javaoop; | |
3587 } | |
3588 | |
3589 // The following "Ideal_foo" functions are placed here because they recognize | |
3590 // the graph shapes created by the functions immediately above. | |
3591 | |
3592 //---------------------------Ideal_allocation---------------------------------- | |
3593 // Given an oop pointer or raw pointer, see if it feeds from an AllocateNode. | |
3594 AllocateNode* AllocateNode::Ideal_allocation(Node* ptr, PhaseTransform* phase) { | |
3595 if (ptr == NULL) { // reduce dumb test in callers | |
3596 return NULL; | |
3597 } | |
11078
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3598 if (ptr->is_CheckCastPP()) { // strip only one raw-to-oop cast |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3599 ptr = ptr->in(1); |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3600 if (ptr == NULL) return NULL; |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3601 } |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3602 // Return NULL for allocations with several casts: |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3603 // j.l.reflect.Array.newInstance(jobject, jint) |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3604 // Object.clone() |
2b3fe74309b6
8019247: SIGSEGV in compiled method c8e.e.t_.getArray(Ljava/lang/Class;)[Ljava/lang/Object
kvn
parents:
10278
diff
changeset
|
3605 // to keep more precise type from last cast. |
0 | 3606 if (ptr->is_Proj()) { |
3607 Node* allo = ptr->in(0); | |
3608 if (allo != NULL && allo->is_Allocate()) { | |
3609 return allo->as_Allocate(); | |
3610 } | |
3611 } | |
3612 // Report failure to match. | |
3613 return NULL; | |
3614 } | |
3615 | |
3616 // Fancy version which also strips off an offset (and reports it to caller). | |
3617 AllocateNode* AllocateNode::Ideal_allocation(Node* ptr, PhaseTransform* phase, | |
3618 intptr_t& offset) { | |
3619 Node* base = AddPNode::Ideal_base_and_offset(ptr, phase, offset); | |
3620 if (base == NULL) return NULL; | |
3621 return Ideal_allocation(base, phase); | |
3622 } | |
3623 | |
3624 // Trace Initialize <- Proj[Parm] <- Allocate | |
3625 AllocateNode* InitializeNode::allocation() { | |
3626 Node* rawoop = in(InitializeNode::RawAddress); | |
3627 if (rawoop->is_Proj()) { | |
3628 Node* alloc = rawoop->in(0); | |
3629 if (alloc->is_Allocate()) { | |
3630 return alloc->as_Allocate(); | |
3631 } | |
3632 } | |
3633 return NULL; | |
3634 } | |
3635 | |
3636 // Trace Allocate -> Proj[Parm] -> Initialize | |
3637 InitializeNode* AllocateNode::initialization() { | |
3638 ProjNode* rawoop = proj_out(AllocateNode::RawAddress); | |
3639 if (rawoop == NULL) return NULL; | |
3640 for (DUIterator_Fast imax, i = rawoop->fast_outs(imax); i < imax; i++) { | |
3641 Node* init = rawoop->fast_out(i); | |
3642 if (init->is_Initialize()) { | |
3643 assert(init->as_Initialize()->allocation() == this, "2-way link"); | |
3644 return init->as_Initialize(); | |
3645 } | |
3646 } | |
3647 return NULL; | |
3648 } | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3649 |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3650 //----------------------------- loop predicates --------------------------- |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3651 |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3652 //------------------------------add_predicate_impl---------------------------- |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3653 void GraphKit::add_predicate_impl(Deoptimization::DeoptReason reason, int nargs) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3654 // Too many traps seen? |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3655 if (too_many_traps(reason)) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3656 #ifdef ASSERT |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3657 if (TraceLoopPredicate) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3658 int tc = C->trap_count(reason); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3659 tty->print("too many traps=%s tcount=%d in ", |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3660 Deoptimization::trap_reason_name(reason), tc); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3661 method()->print(); // which method has too many predicate traps |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3662 tty->cr(); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3663 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3664 #endif |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3665 // We cannot afford to take more traps here, |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3666 // do not generate predicate. |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3667 return; |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3668 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3669 |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3670 Node *cont = _gvn.intcon(1); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3671 Node* opq = _gvn.transform(new (C) Opaque1Node(C, cont)); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3672 Node *bol = _gvn.transform(new (C) Conv2BNode(opq)); |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3673 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3674 Node* iffalse = _gvn.transform(new (C) IfFalseNode(iff)); |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3675 C->add_predicate_opaq(opq); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3676 { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3677 PreserveJVMState pjvms(this); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3678 set_control(iffalse); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6846
diff
changeset
|
3679 inc_sp(nargs); |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3680 uncommon_trap(reason, Deoptimization::Action_maybe_recompile); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3681 } |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
3682 Node* iftrue = _gvn.transform(new (C) IfTrueNode(iff)); |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3683 set_control(iftrue); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3684 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3685 |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3686 //------------------------------add_predicate--------------------------------- |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3687 void GraphKit::add_predicate(int nargs) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3688 if (UseLoopPredicate) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3689 add_predicate_impl(Deoptimization::Reason_predicate, nargs); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3690 } |
3345 | 3691 // loop's limit check predicate should be near the loop. |
3692 if (LoopLimitCheck) { | |
3693 add_predicate_impl(Deoptimization::Reason_loop_limit_check, nargs); | |
3694 } | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3695 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2007
diff
changeset
|
3696 |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3697 //----------------------------- store barriers ---------------------------- |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3698 #define __ ideal. |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3699 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3700 void GraphKit::sync_kit(IdealKit& ideal) { |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3701 set_all_memory(__ merged_memory()); |
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3702 set_i_o(__ i_o()); |
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3703 set_control(__ ctrl()); |
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3704 } |
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3705 |
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3706 void GraphKit::final_sync(IdealKit& ideal) { |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3707 // Final sync IdealKit and graphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3708 sync_kit(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3709 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3710 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3711 // vanilla/CMS post barrier |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3712 // Insert a write-barrier store. This is to let generational GC work; we have |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3713 // to flag all oop-stores before the next GC point. |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3714 void GraphKit::write_barrier_post(Node* oop_store, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3715 Node* obj, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3716 Node* adr, |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
3717 uint adr_idx, |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3718 Node* val, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3719 bool use_precise) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3720 // No store check needed if we're storing a NULL or an old object |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3721 // (latter case is probably a string constant). The concurrent |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3722 // mark sweep garbage collector, however, needs to have all nonNull |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3723 // oop updates flagged via card-marks. |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3724 if (val != NULL && val->is_Con()) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3725 // must be either an oop or NULL |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3726 const Type* t = val->bottom_type(); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3727 if (t == TypePtr::NULL_PTR || t == Type::TOP) |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3728 // stores of null never (?) need barriers |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3729 return; |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3730 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3731 |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3732 if (use_ReduceInitialCardMarks() |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3733 && obj == just_allocated_object(control())) { |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3734 // We can skip marks on a freshly-allocated object in Eden. |
1166 | 3735 // Keep this code in sync with new_store_pre_barrier() in runtime.cpp. |
3736 // That routine informs GC to take appropriate compensating steps, | |
3737 // upon a slow-path allocation, so as to make this card-mark | |
3738 // elision safe. | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3739 return; |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3740 } |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
985
diff
changeset
|
3741 |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3742 if (!use_precise) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3743 // All card marks for a (non-array) instance are in one place: |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3744 adr = obj; |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3745 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3746 // (Else it's an array (or unknown), and we want more precise card marks.) |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3747 assert(adr != NULL, ""); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3748 |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3749 IdealKit ideal(this, true); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3750 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3751 // Convert the pointer to an int prior to doing math on it |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3752 Node* cast = __ CastPX(__ ctrl(), adr); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3753 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3754 // Divide by card size |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3755 assert(Universe::heap()->barrier_set()->kind() == BarrierSet::CardTableModRef, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3756 "Only one we handle so far."); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3757 Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) ); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3758 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3759 // Combine card table base and card offset |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3760 Node* card_adr = __ AddP(__ top(), byte_map_base_node(), card_offset ); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3761 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3762 // Get the alias_index for raw card-mark memory |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3763 int adr_type = Compile::AliasIdxRaw; |
3282 | 3764 Node* zero = __ ConI(0); // Dirty card value |
3765 BasicType bt = T_BYTE; | |
3766 | |
3767 if (UseCondCardMark) { | |
3768 // The classic GC reference write barrier is typically implemented | |
3769 // as a store into the global card mark table. Unfortunately | |
3770 // unconditional stores can result in false sharing and excessive | |
3771 // coherence traffic as well as false transactional aborts. | |
3772 // UseCondCardMark enables MP "polite" conditional card mark | |
3773 // stores. In theory we could relax the load from ctrl() to | |
3774 // no_ctrl, but that doesn't buy much latitude. | |
3775 Node* card_val = __ load( __ ctrl(), card_adr, TypeInt::BYTE, bt, adr_type); | |
3776 __ if_then(card_val, BoolTest::ne, zero); | |
3777 } | |
3778 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3779 // Smash zero into card |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3780 if( !UseConcMarkSweepGC ) { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3781 __ store(__ ctrl(), card_adr, zero, bt, adr_type, MemNode::release); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3782 } else { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3783 // Specialized path for CM store barrier |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
3784 __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3785 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3786 |
3282 | 3787 if (UseCondCardMark) { |
3788 __ end_if(); | |
3789 } | |
3790 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3791 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3792 final_sync(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3793 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3794 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3795 // G1 pre/post barriers |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3796 void GraphKit::g1_write_barrier_pre(bool do_load, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3797 Node* obj, |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3798 Node* adr, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3799 uint alias_idx, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3800 Node* val, |
825 | 3801 const TypeOopPtr* val_type, |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3802 Node* pre_val, |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3803 BasicType bt) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3804 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3805 // Some sanity checks |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3806 // Note: val is unused in this routine. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3807 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3808 if (do_load) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3809 // We need to generate the load of the previous value |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3810 assert(obj != NULL, "must have a base"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3811 assert(adr != NULL, "where are loading from?"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3812 assert(pre_val == NULL, "loaded already?"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3813 assert(val_type != NULL, "need a type"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3814 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3815 // In this case both val_type and alias_idx are unused. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3816 assert(pre_val != NULL, "must be loaded already"); |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
3817 // Nothing to be done if pre_val is null. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12159
diff
changeset
|
3818 if (pre_val->bottom_type() == TypePtr::NULL_PTR) return; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3819 assert(pre_val->bottom_type()->basic_type() == T_OBJECT, "or we shouldn't be here"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3820 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3821 assert(bt == T_OBJECT, "or we shouldn't be here"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3822 |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3823 IdealKit ideal(this, true); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3824 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3825 Node* tls = __ thread(); // ThreadLocalStorage |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3826 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3827 Node* no_ctrl = NULL; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3828 Node* no_base = __ top(); |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3829 Node* zero = __ ConI(0); |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3830 Node* zeroX = __ ConX(0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3831 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3832 float likely = PROB_LIKELY(0.999); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3833 float unlikely = PROB_UNLIKELY(0.999); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3834 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3835 BasicType active_type = in_bytes(PtrQueue::byte_width_of_active()) == 4 ? T_INT : T_BYTE; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3836 assert(in_bytes(PtrQueue::byte_width_of_active()) == 4 || in_bytes(PtrQueue::byte_width_of_active()) == 1, "flag width"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3837 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3838 // Offsets into the thread |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3839 const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + // 648 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3840 PtrQueue::byte_offset_of_active()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3841 const int index_offset = in_bytes(JavaThread::satb_mark_queue_offset() + // 656 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3842 PtrQueue::byte_offset_of_index()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3843 const int buffer_offset = in_bytes(JavaThread::satb_mark_queue_offset() + // 652 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3844 PtrQueue::byte_offset_of_buf()); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3845 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3846 // Now the actual pointers into the thread |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3847 Node* marking_adr = __ AddP(no_base, tls, __ ConX(marking_offset)); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3848 Node* buffer_adr = __ AddP(no_base, tls, __ ConX(buffer_offset)); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3849 Node* index_adr = __ AddP(no_base, tls, __ ConX(index_offset)); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3850 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3851 // Now some of the values |
544
82a980778b92
6793828: G1: invariant: queues are empty when activated
never
parents:
372
diff
changeset
|
3852 Node* marking = __ load(__ ctrl(), marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3853 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3854 // if (!marking) |
12886 | 3855 __ if_then(marking, BoolTest::ne, zero, unlikely); { |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3856 BasicType index_bt = TypeX_X->basic_type(); |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3857 assert(sizeof(size_t) == type2aelembytes(index_bt), "Loading G1 PtrQueue::_index with wrong size."); |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3858 Node* index = __ load(__ ctrl(), index_adr, TypeX_X, index_bt, Compile::AliasIdxRaw); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3859 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3860 if (do_load) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3861 // load original value |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3862 // alias_idx correct?? |
12159 | 3863 pre_val = __ load(__ ctrl(), adr, val_type, bt, alias_idx); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3864 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3865 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3866 // if (pre_val != NULL) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3867 __ if_then(pre_val, BoolTest::ne, null()); { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3868 Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3869 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3870 // is the queue for this thread full? |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3871 __ if_then(index, BoolTest::ne, zeroX, likely); { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3872 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3873 // decrement the index |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3874 Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3875 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3876 // Now get the buffer location we will log the previous value into and store it |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3877 Node *log_addr = __ AddP(no_base, buffer, next_index); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3878 __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw, MemNode::unordered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3879 // update the index |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3880 __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw, MemNode::unordered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3881 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3882 } __ else_(); { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3883 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3884 // logging buffer is full, call the runtime |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3885 const TypeFunc *tf = OptoRuntime::g1_wb_pre_Type(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3886 __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), "g1_wb_pre", pre_val, tls); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3887 } __ end_if(); // (!index) |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2383
diff
changeset
|
3888 } __ end_if(); // (pre_val != NULL) |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3889 } __ end_if(); // (!marking) |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3890 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3891 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3892 final_sync(ideal); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3893 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3894 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3895 // |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3896 // Update the card table and add card address to the queue |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3897 // |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3898 void GraphKit::g1_mark_card(IdealKit& ideal, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3899 Node* card_adr, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3900 Node* oop_store, |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
3901 uint oop_alias_idx, |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3902 Node* index, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3903 Node* index_adr, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3904 Node* buffer, |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3905 const TypeFunc* tf) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3906 |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3907 Node* zero = __ ConI(0); |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3908 Node* zeroX = __ ConX(0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3909 Node* no_base = __ top(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3910 BasicType card_bt = T_BYTE; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3911 // Smash zero into card. MUST BE ORDERED WRT TO STORE |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
3912 __ storeCM(__ ctrl(), card_adr, zero, oop_store, oop_alias_idx, card_bt, Compile::AliasIdxRaw); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3913 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3914 // Now do the queue work |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3915 __ if_then(index, BoolTest::ne, zeroX); { |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3916 |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3917 Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); |
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3918 Node* log_addr = __ AddP(no_base, buffer, next_index); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3919 |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3920 // Order, see storeCM. |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3921 __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered); |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
3922 __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw, MemNode::unordered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3923 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3924 } __ else_(); { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3925 __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3926 } __ end_if(); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3927 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3928 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3929 |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3930 void GraphKit::g1_write_barrier_post(Node* oop_store, |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3931 Node* obj, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3932 Node* adr, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3933 uint alias_idx, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3934 Node* val, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3935 BasicType bt, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3936 bool use_precise) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3937 // If we are writing a NULL then we need no post barrier |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3938 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3939 if (val != NULL && val->is_Con() && val->bottom_type() == TypePtr::NULL_PTR) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3940 // Must be NULL |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3941 const Type* t = val->bottom_type(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3942 assert(t == Type::TOP || t == TypePtr::NULL_PTR, "must be NULL"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3943 // No post barrier if writing NULLx |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3944 return; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3945 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3946 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3947 if (!use_precise) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3948 // All card marks for a (non-array) instance are in one place: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3949 adr = obj; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3950 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3951 // (Else it's an array (or unknown), and we want more precise card marks.) |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3952 assert(adr != NULL, ""); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3953 |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
3954 IdealKit ideal(this, true); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3955 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3956 Node* tls = __ thread(); // ThreadLocalStorage |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3957 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3958 Node* no_base = __ top(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3959 float likely = PROB_LIKELY(0.999); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3960 float unlikely = PROB_UNLIKELY(0.999); |
12835
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
3961 Node* young_card = __ ConI((jint)G1SATBCardTableModRefBS::g1_young_card_val()); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
3962 Node* dirty_card = __ ConI((jint)CardTableModRefBS::dirty_card_val()); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3963 Node* zeroX = __ ConX(0); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3964 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3965 // Get the alias_index for raw card-mark memory |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3966 const TypePtr* card_type = TypeRawPtr::BOTTOM; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3967 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3968 const TypeFunc *tf = OptoRuntime::g1_wb_post_Type(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3969 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3970 // Offsets into the thread |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3971 const int index_offset = in_bytes(JavaThread::dirty_card_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3972 PtrQueue::byte_offset_of_index()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3973 const int buffer_offset = in_bytes(JavaThread::dirty_card_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3974 PtrQueue::byte_offset_of_buf()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3975 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3976 // Pointers into the thread |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3977 |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3978 Node* buffer_adr = __ AddP(no_base, tls, __ ConX(buffer_offset)); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3979 Node* index_adr = __ AddP(no_base, tls, __ ConX(index_offset)); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3980 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3981 // Now some values |
1593
2458a1f25356
6953058: G1: A bigapp crashes with SIGSEGV in compiled code
johnc
parents:
1397
diff
changeset
|
3982 // Use ctrl to avoid hoisting these values past a safepoint, which could |
2458a1f25356
6953058: G1: A bigapp crashes with SIGSEGV in compiled code
johnc
parents:
1397
diff
changeset
|
3983 // potentially reset these fields in the JavaThread. |
10185
d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
johnc
parents:
8868
diff
changeset
|
3984 Node* index = __ load(__ ctrl(), index_adr, TypeX_X, TypeX_X->basic_type(), Compile::AliasIdxRaw); |
1593
2458a1f25356
6953058: G1: A bigapp crashes with SIGSEGV in compiled code
johnc
parents:
1397
diff
changeset
|
3985 Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3986 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3987 // Convert the store obj pointer to an int prior to doing math on it |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3988 // Must use ctrl to prevent "integerized oop" existing across safepoint |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3989 Node* cast = __ CastPX(__ ctrl(), adr); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3990 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3991 // Divide pointer by card size |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3992 Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) ); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3993 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3994 // Combine card table base and card offset |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
3995 Node* card_adr = __ AddP(no_base, byte_map_base_node(), card_offset ); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3996 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3997 // If we know the value being stored does it cross regions? |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3998 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3999 if (val != NULL) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4000 // Does the store cause us to cross regions? |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4001 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4002 // Should be able to do an unsigned compare of region_size instead of |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4003 // and extra shift. Do we have an unsigned compare?? |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4004 // Node* region_size = __ ConI(1 << HeapRegion::LogOfHRGrainBytes); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4005 Node* xor_res = __ URShiftX ( __ XorX( cast, __ CastPX(__ ctrl(), val)), __ ConI(HeapRegion::LogOfHRGrainBytes)); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4006 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4007 // if (xor_res == 0) same region so skip |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4008 __ if_then(xor_res, BoolTest::ne, zeroX); { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4009 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4010 // No barrier if we are storing a NULL |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4011 __ if_then(val, BoolTest::ne, null(), unlikely); { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4012 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4013 // Ok must mark the card if not already dirty |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4014 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4015 // load the original value of the card |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4016 Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4017 |
12835
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4018 __ if_then(card_val, BoolTest::ne, young_card); { |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4019 sync_kit(ideal); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4020 // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier. |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4021 insert_mem_bar(Op_MemBarVolatile, oop_store); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4022 __ sync_kit(this); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4023 |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4024 Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4025 __ if_then(card_val_reload, BoolTest::ne, dirty_card); { |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4026 g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); |
69944b868a32
8014555: G1: Memory ordering problem with Conc refinement and card marking
mgerdin
parents:
12190
diff
changeset
|
4027 } __ end_if(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4028 } __ end_if(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4029 } __ end_if(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4030 } __ end_if(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4031 } else { |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
4032 // Object.clone() instrinsic uses this path. |
985
685e959d09ea
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
955
diff
changeset
|
4033 g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4034 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4035 |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
4036 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2383
diff
changeset
|
4037 final_sync(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
827
diff
changeset
|
4038 } |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
4039 #undef __ |
6057 | 4040 |
4041 | |
4042 | |
4043 Node* GraphKit::load_String_offset(Node* ctrl, Node* str) { | |
4044 if (java_lang_String::has_offset_field()) { | |
4045 int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
4046 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4047 false, NULL, 0); | |
4048 const TypePtr* offset_field_type = string_type->add_offset(offset_offset); | |
4049 int offset_field_idx = C->get_alias_index(offset_field_type); | |
4050 return make_load(ctrl, | |
4051 basic_plus_adr(str, str, offset_offset), | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4052 TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered); |
6057 | 4053 } else { |
4054 return intcon(0); | |
4055 } | |
4056 } | |
4057 | |
4058 Node* GraphKit::load_String_length(Node* ctrl, Node* str) { | |
4059 if (java_lang_String::has_count_field()) { | |
4060 int count_offset = java_lang_String::count_offset_in_bytes(); | |
4061 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4062 false, NULL, 0); | |
4063 const TypePtr* count_field_type = string_type->add_offset(count_offset); | |
4064 int count_field_idx = C->get_alias_index(count_field_type); | |
4065 return make_load(ctrl, | |
4066 basic_plus_adr(str, str, count_offset), | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4067 TypeInt::INT, T_INT, count_field_idx, MemNode::unordered); |
6057 | 4068 } else { |
4069 return load_array_length(load_String_value(ctrl, str)); | |
4070 } | |
4071 } | |
4072 | |
4073 Node* GraphKit::load_String_value(Node* ctrl, Node* str) { | |
4074 int value_offset = java_lang_String::value_offset_in_bytes(); | |
4075 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4076 false, NULL, 0); | |
4077 const TypePtr* value_field_type = string_type->add_offset(value_offset); | |
4078 const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, | |
4079 TypeAry::make(TypeInt::CHAR,TypeInt::POS), | |
4080 ciTypeArrayKlass::make(T_CHAR), true, 0); | |
4081 int value_field_idx = C->get_alias_index(value_field_type); | |
12190
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4082 Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4083 value_type, T_OBJECT, value_field_idx, MemNode::unordered); |
12190
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4084 // String.value field is known to be @Stable. |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4085 if (UseImplicitStableValues) { |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4086 load = cast_array_to_stable(load, value_type); |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4087 } |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4088 return load; |
6057 | 4089 } |
4090 | |
4091 void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) { | |
4092 int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
4093 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4094 false, NULL, 0); | |
4095 const TypePtr* offset_field_type = string_type->add_offset(offset_offset); | |
4096 int offset_field_idx = C->get_alias_index(offset_field_type); | |
4097 store_to_memory(ctrl, basic_plus_adr(str, offset_offset), | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4098 value, T_INT, offset_field_idx, MemNode::unordered); |
6057 | 4099 } |
4100 | |
4101 void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { | |
4102 int value_offset = java_lang_String::value_offset_in_bytes(); | |
4103 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4104 false, NULL, 0); | |
4105 const TypePtr* value_field_type = string_type->add_offset(value_offset); | |
12331
d8d059e90ec1
8025599: Missing store barrier with OptimizeStringConcat
twisti
parents:
12190
diff
changeset
|
4106 |
d8d059e90ec1
8025599: Missing store barrier with OptimizeStringConcat
twisti
parents:
12190
diff
changeset
|
4107 store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4108 value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered); |
6057 | 4109 } |
4110 | |
4111 void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { | |
4112 int count_offset = java_lang_String::count_offset_in_bytes(); | |
4113 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), | |
4114 false, NULL, 0); | |
4115 const TypePtr* count_field_type = string_type->add_offset(count_offset); | |
4116 int count_field_idx = C->get_alias_index(count_field_type); | |
4117 store_to_memory(ctrl, basic_plus_adr(str, count_offset), | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
12966
diff
changeset
|
4118 value, T_INT, count_field_idx, MemNode::unordered); |
6057 | 4119 } |
12190
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4120 |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4121 Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4122 // Reify the property as a CastPP node in Ideal graph to comply with monotonicity |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4123 // assumption of CCP analysis. |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4124 return _gvn.transform(new(C) CastPPNode(ary, ary_type->cast_to_stable(true))); |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
4125 } |