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