Mercurial > hg > truffle
annotate src/share/vm/c1/c1_GraphBuilder.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 945284eb609f |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1540
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1540
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:
1540
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "c1/c1_CFGPrinter.hpp" | |
27 #include "c1/c1_Canonicalizer.hpp" | |
28 #include "c1/c1_Compilation.hpp" | |
29 #include "c1/c1_GraphBuilder.hpp" | |
30 #include "c1/c1_InstructionPrinter.hpp" | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
31 #include "ci/ciCallSite.hpp" |
1972 | 32 #include "ci/ciField.hpp" |
33 #include "ci/ciKlass.hpp" | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
34 #include "ci/ciMemberName.hpp" |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2376
diff
changeset
|
35 #include "compiler/compileBroker.hpp" |
1972 | 36 #include "interpreter/bytecode.hpp" |
37 #include "runtime/sharedRuntime.hpp" | |
3791
2c359f27615c
7057120: Tiered: Allow C1 to inline methods with loops
iveresov
parents:
3255
diff
changeset
|
38 #include "runtime/compilationPolicy.hpp" |
1972 | 39 #include "utilities/bitMap.inline.hpp" |
0 | 40 |
41 class BlockListBuilder VALUE_OBJ_CLASS_SPEC { | |
42 private: | |
43 Compilation* _compilation; | |
44 IRScope* _scope; | |
45 | |
46 BlockList _blocks; // internal list of all blocks | |
47 BlockList* _bci2block; // mapping from bci to blocks for GraphBuilder | |
48 | |
49 // fields used by mark_loops | |
50 BitMap _active; // for iteration of control flow graph | |
51 BitMap _visited; // for iteration of control flow graph | |
52 intArray _loop_map; // caches the information if a block is contained in a loop | |
53 int _next_loop_index; // next free loop number | |
54 int _next_block_number; // for reverse postorder numbering of blocks | |
55 | |
56 // accessors | |
57 Compilation* compilation() const { return _compilation; } | |
58 IRScope* scope() const { return _scope; } | |
59 ciMethod* method() const { return scope()->method(); } | |
60 XHandlers* xhandlers() const { return scope()->xhandlers(); } | |
61 | |
62 // unified bailout support | |
63 void bailout(const char* msg) const { compilation()->bailout(msg); } | |
64 bool bailed_out() const { return compilation()->bailed_out(); } | |
65 | |
66 // helper functions | |
67 BlockBegin* make_block_at(int bci, BlockBegin* predecessor); | |
68 void handle_exceptions(BlockBegin* current, int cur_bci); | |
69 void handle_jsr(BlockBegin* current, int sr_bci, int next_bci); | |
70 void store_one(BlockBegin* current, int local); | |
71 void store_two(BlockBegin* current, int local); | |
72 void set_entries(int osr_bci); | |
73 void set_leaders(); | |
74 | |
75 void make_loop_header(BlockBegin* block); | |
76 void mark_loops(); | |
77 int mark_loops(BlockBegin* b, bool in_subroutine); | |
78 | |
79 // debugging | |
80 #ifndef PRODUCT | |
81 void print(); | |
82 #endif | |
83 | |
84 public: | |
85 // creation | |
86 BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci); | |
87 | |
88 // accessors for GraphBuilder | |
89 BlockList* bci2block() const { return _bci2block; } | |
90 }; | |
91 | |
92 | |
93 // Implementation of BlockListBuilder | |
94 | |
95 BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci) | |
96 : _compilation(compilation) | |
97 , _scope(scope) | |
98 , _blocks(16) | |
99 , _bci2block(new BlockList(scope->method()->code_size(), NULL)) | |
100 , _next_block_number(0) | |
101 , _active() // size not known yet | |
102 , _visited() // size not known yet | |
103 , _next_loop_index(0) | |
104 , _loop_map() // size not known yet | |
105 { | |
106 set_entries(osr_bci); | |
107 set_leaders(); | |
108 CHECK_BAILOUT(); | |
109 | |
110 mark_loops(); | |
111 NOT_PRODUCT(if (PrintInitialBlockList) print()); | |
112 | |
113 #ifndef PRODUCT | |
114 if (PrintCFGToFile) { | |
115 stringStream title; | |
116 title.print("BlockListBuilder "); | |
117 scope->method()->print_name(&title); | |
118 CFGPrinter::print_cfg(_bci2block, title.as_string(), false, false); | |
119 } | |
120 #endif | |
121 } | |
122 | |
123 | |
124 void BlockListBuilder::set_entries(int osr_bci) { | |
125 // generate start blocks | |
126 BlockBegin* std_entry = make_block_at(0, NULL); | |
127 if (scope()->caller() == NULL) { | |
128 std_entry->set(BlockBegin::std_entry_flag); | |
129 } | |
130 if (osr_bci != -1) { | |
131 BlockBegin* osr_entry = make_block_at(osr_bci, NULL); | |
132 osr_entry->set(BlockBegin::osr_entry_flag); | |
133 } | |
134 | |
135 // generate exception entry blocks | |
136 XHandlers* list = xhandlers(); | |
137 const int n = list->length(); | |
138 for (int i = 0; i < n; i++) { | |
139 XHandler* h = list->handler_at(i); | |
140 BlockBegin* entry = make_block_at(h->handler_bci(), NULL); | |
141 entry->set(BlockBegin::exception_entry_flag); | |
142 h->set_entry_block(entry); | |
143 } | |
144 } | |
145 | |
146 | |
147 BlockBegin* BlockListBuilder::make_block_at(int cur_bci, BlockBegin* predecessor) { | |
148 assert(method()->bci_block_start().at(cur_bci), "wrong block starts of MethodLivenessAnalyzer"); | |
149 | |
150 BlockBegin* block = _bci2block->at(cur_bci); | |
151 if (block == NULL) { | |
152 block = new BlockBegin(cur_bci); | |
153 block->init_stores_to_locals(method()->max_locals()); | |
154 _bci2block->at_put(cur_bci, block); | |
155 _blocks.append(block); | |
156 | |
157 assert(predecessor == NULL || predecessor->bci() < cur_bci, "targets for backward branches must already exist"); | |
158 } | |
159 | |
160 if (predecessor != NULL) { | |
161 if (block->is_set(BlockBegin::exception_entry_flag)) { | |
162 BAILOUT_("Exception handler can be reached by both normal and exceptional control flow", block); | |
163 } | |
164 | |
165 predecessor->add_successor(block); | |
166 block->increment_total_preds(); | |
167 } | |
168 | |
169 return block; | |
170 } | |
171 | |
172 | |
173 inline void BlockListBuilder::store_one(BlockBegin* current, int local) { | |
174 current->stores_to_locals().set_bit(local); | |
175 } | |
176 inline void BlockListBuilder::store_two(BlockBegin* current, int local) { | |
177 store_one(current, local); | |
178 store_one(current, local + 1); | |
179 } | |
180 | |
181 | |
182 void BlockListBuilder::handle_exceptions(BlockBegin* current, int cur_bci) { | |
183 // Draws edges from a block to its exception handlers | |
184 XHandlers* list = xhandlers(); | |
185 const int n = list->length(); | |
186 | |
187 for (int i = 0; i < n; i++) { | |
188 XHandler* h = list->handler_at(i); | |
189 | |
190 if (h->covers(cur_bci)) { | |
191 BlockBegin* entry = h->entry_block(); | |
192 assert(entry != NULL && entry == _bci2block->at(h->handler_bci()), "entry must be set"); | |
193 assert(entry->is_set(BlockBegin::exception_entry_flag), "flag must be set"); | |
194 | |
195 // add each exception handler only once | |
196 if (!current->is_successor(entry)) { | |
197 current->add_successor(entry); | |
198 entry->increment_total_preds(); | |
199 } | |
200 | |
201 // stop when reaching catchall | |
202 if (h->catch_type() == 0) break; | |
203 } | |
204 } | |
205 } | |
206 | |
207 void BlockListBuilder::handle_jsr(BlockBegin* current, int sr_bci, int next_bci) { | |
208 // start a new block after jsr-bytecode and link this block into cfg | |
209 make_block_at(next_bci, current); | |
210 | |
211 // start a new block at the subroutine entry at mark it with special flag | |
212 BlockBegin* sr_block = make_block_at(sr_bci, current); | |
213 if (!sr_block->is_set(BlockBegin::subroutine_entry_flag)) { | |
214 sr_block->set(BlockBegin::subroutine_entry_flag); | |
215 } | |
216 } | |
217 | |
218 | |
219 void BlockListBuilder::set_leaders() { | |
220 bool has_xhandlers = xhandlers()->has_handlers(); | |
221 BlockBegin* current = NULL; | |
222 | |
223 // The information which bci starts a new block simplifies the analysis | |
224 // Without it, backward branches could jump to a bci where no block was created | |
225 // during bytecode iteration. This would require the creation of a new block at the | |
226 // branch target and a modification of the successor lists. | |
227 BitMap bci_block_start = method()->bci_block_start(); | |
228 | |
229 ciBytecodeStream s(method()); | |
230 while (s.next() != ciBytecodeStream::EOBC()) { | |
231 int cur_bci = s.cur_bci(); | |
232 | |
233 if (bci_block_start.at(cur_bci)) { | |
234 current = make_block_at(cur_bci, current); | |
235 } | |
236 assert(current != NULL, "must have current block"); | |
237 | |
238 if (has_xhandlers && GraphBuilder::can_trap(method(), s.cur_bc())) { | |
239 handle_exceptions(current, cur_bci); | |
240 } | |
241 | |
242 switch (s.cur_bc()) { | |
243 // track stores to local variables for selective creation of phi functions | |
244 case Bytecodes::_iinc: store_one(current, s.get_index()); break; | |
245 case Bytecodes::_istore: store_one(current, s.get_index()); break; | |
246 case Bytecodes::_lstore: store_two(current, s.get_index()); break; | |
247 case Bytecodes::_fstore: store_one(current, s.get_index()); break; | |
248 case Bytecodes::_dstore: store_two(current, s.get_index()); break; | |
249 case Bytecodes::_astore: store_one(current, s.get_index()); break; | |
250 case Bytecodes::_istore_0: store_one(current, 0); break; | |
251 case Bytecodes::_istore_1: store_one(current, 1); break; | |
252 case Bytecodes::_istore_2: store_one(current, 2); break; | |
253 case Bytecodes::_istore_3: store_one(current, 3); break; | |
254 case Bytecodes::_lstore_0: store_two(current, 0); break; | |
255 case Bytecodes::_lstore_1: store_two(current, 1); break; | |
256 case Bytecodes::_lstore_2: store_two(current, 2); break; | |
257 case Bytecodes::_lstore_3: store_two(current, 3); break; | |
258 case Bytecodes::_fstore_0: store_one(current, 0); break; | |
259 case Bytecodes::_fstore_1: store_one(current, 1); break; | |
260 case Bytecodes::_fstore_2: store_one(current, 2); break; | |
261 case Bytecodes::_fstore_3: store_one(current, 3); break; | |
262 case Bytecodes::_dstore_0: store_two(current, 0); break; | |
263 case Bytecodes::_dstore_1: store_two(current, 1); break; | |
264 case Bytecodes::_dstore_2: store_two(current, 2); break; | |
265 case Bytecodes::_dstore_3: store_two(current, 3); break; | |
266 case Bytecodes::_astore_0: store_one(current, 0); break; | |
267 case Bytecodes::_astore_1: store_one(current, 1); break; | |
268 case Bytecodes::_astore_2: store_one(current, 2); break; | |
269 case Bytecodes::_astore_3: store_one(current, 3); break; | |
270 | |
271 // track bytecodes that affect the control flow | |
272 case Bytecodes::_athrow: // fall through | |
273 case Bytecodes::_ret: // fall through | |
274 case Bytecodes::_ireturn: // fall through | |
275 case Bytecodes::_lreturn: // fall through | |
276 case Bytecodes::_freturn: // fall through | |
277 case Bytecodes::_dreturn: // fall through | |
278 case Bytecodes::_areturn: // fall through | |
279 case Bytecodes::_return: | |
280 current = NULL; | |
281 break; | |
282 | |
283 case Bytecodes::_ifeq: // fall through | |
284 case Bytecodes::_ifne: // fall through | |
285 case Bytecodes::_iflt: // fall through | |
286 case Bytecodes::_ifge: // fall through | |
287 case Bytecodes::_ifgt: // fall through | |
288 case Bytecodes::_ifle: // fall through | |
289 case Bytecodes::_if_icmpeq: // fall through | |
290 case Bytecodes::_if_icmpne: // fall through | |
291 case Bytecodes::_if_icmplt: // fall through | |
292 case Bytecodes::_if_icmpge: // fall through | |
293 case Bytecodes::_if_icmpgt: // fall through | |
294 case Bytecodes::_if_icmple: // fall through | |
295 case Bytecodes::_if_acmpeq: // fall through | |
296 case Bytecodes::_if_acmpne: // fall through | |
297 case Bytecodes::_ifnull: // fall through | |
298 case Bytecodes::_ifnonnull: | |
299 make_block_at(s.next_bci(), current); | |
300 make_block_at(s.get_dest(), current); | |
301 current = NULL; | |
302 break; | |
303 | |
304 case Bytecodes::_goto: | |
305 make_block_at(s.get_dest(), current); | |
306 current = NULL; | |
307 break; | |
308 | |
309 case Bytecodes::_goto_w: | |
310 make_block_at(s.get_far_dest(), current); | |
311 current = NULL; | |
312 break; | |
313 | |
314 case Bytecodes::_jsr: | |
315 handle_jsr(current, s.get_dest(), s.next_bci()); | |
316 current = NULL; | |
317 break; | |
318 | |
319 case Bytecodes::_jsr_w: | |
320 handle_jsr(current, s.get_far_dest(), s.next_bci()); | |
321 current = NULL; | |
322 break; | |
323 | |
324 case Bytecodes::_tableswitch: { | |
325 // set block for each case | |
2142 | 326 Bytecode_tableswitch sw(&s); |
327 int l = sw.length(); | |
0 | 328 for (int i = 0; i < l; i++) { |
2142 | 329 make_block_at(cur_bci + sw.dest_offset_at(i), current); |
0 | 330 } |
2142 | 331 make_block_at(cur_bci + sw.default_offset(), current); |
0 | 332 current = NULL; |
333 break; | |
334 } | |
335 | |
336 case Bytecodes::_lookupswitch: { | |
337 // set block for each case | |
2142 | 338 Bytecode_lookupswitch sw(&s); |
339 int l = sw.number_of_pairs(); | |
0 | 340 for (int i = 0; i < l; i++) { |
2142 | 341 make_block_at(cur_bci + sw.pair_at(i).offset(), current); |
0 | 342 } |
2142 | 343 make_block_at(cur_bci + sw.default_offset(), current); |
0 | 344 current = NULL; |
345 break; | |
346 } | |
347 } | |
348 } | |
349 } | |
350 | |
351 | |
352 void BlockListBuilder::mark_loops() { | |
353 ResourceMark rm; | |
354 | |
355 _active = BitMap(BlockBegin::number_of_blocks()); _active.clear(); | |
356 _visited = BitMap(BlockBegin::number_of_blocks()); _visited.clear(); | |
357 _loop_map = intArray(BlockBegin::number_of_blocks(), 0); | |
358 _next_loop_index = 0; | |
359 _next_block_number = _blocks.length(); | |
360 | |
361 // recursively iterate the control flow graph | |
362 mark_loops(_bci2block->at(0), false); | |
363 assert(_next_block_number >= 0, "invalid block numbers"); | |
364 } | |
365 | |
366 void BlockListBuilder::make_loop_header(BlockBegin* block) { | |
367 if (block->is_set(BlockBegin::exception_entry_flag)) { | |
368 // exception edges may look like loops but don't mark them as such | |
369 // since it screws up block ordering. | |
370 return; | |
371 } | |
372 if (!block->is_set(BlockBegin::parser_loop_header_flag)) { | |
373 block->set(BlockBegin::parser_loop_header_flag); | |
374 | |
375 assert(_loop_map.at(block->block_id()) == 0, "must not be set yet"); | |
376 assert(0 <= _next_loop_index && _next_loop_index < BitsPerInt, "_next_loop_index is used as a bit-index in integer"); | |
377 _loop_map.at_put(block->block_id(), 1 << _next_loop_index); | |
378 if (_next_loop_index < 31) _next_loop_index++; | |
379 } else { | |
380 // block already marked as loop header | |
1060 | 381 assert(is_power_of_2((unsigned int)_loop_map.at(block->block_id())), "exactly one bit must be set"); |
0 | 382 } |
383 } | |
384 | |
385 int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { | |
386 int block_id = block->block_id(); | |
387 | |
388 if (_visited.at(block_id)) { | |
389 if (_active.at(block_id)) { | |
390 // reached block via backward branch | |
391 make_loop_header(block); | |
392 } | |
393 // return cached loop information for this block | |
394 return _loop_map.at(block_id); | |
395 } | |
396 | |
397 if (block->is_set(BlockBegin::subroutine_entry_flag)) { | |
398 in_subroutine = true; | |
399 } | |
400 | |
401 // set active and visited bits before successors are processed | |
402 _visited.set_bit(block_id); | |
403 _active.set_bit(block_id); | |
404 | |
405 intptr_t loop_state = 0; | |
406 for (int i = block->number_of_sux() - 1; i >= 0; i--) { | |
407 // recursively process all successors | |
408 loop_state |= mark_loops(block->sux_at(i), in_subroutine); | |
409 } | |
410 | |
411 // clear active-bit after all successors are processed | |
412 _active.clear_bit(block_id); | |
413 | |
414 // reverse-post-order numbering of all blocks | |
415 block->set_depth_first_number(_next_block_number); | |
416 _next_block_number--; | |
417 | |
418 if (loop_state != 0 || in_subroutine ) { | |
419 // block is contained at least in one loop, so phi functions are necessary | |
420 // phi functions are also necessary for all locals stored in a subroutine | |
421 scope()->requires_phi_function().set_union(block->stores_to_locals()); | |
422 } | |
423 | |
424 if (block->is_set(BlockBegin::parser_loop_header_flag)) { | |
425 int header_loop_state = _loop_map.at(block_id); | |
426 assert(is_power_of_2((unsigned)header_loop_state), "exactly one bit must be set"); | |
427 | |
428 // If the highest bit is set (i.e. when integer value is negative), the method | |
429 // has 32 or more loops. This bit is never cleared because it is used for multiple loops | |
430 if (header_loop_state >= 0) { | |
431 clear_bits(loop_state, header_loop_state); | |
432 } | |
433 } | |
434 | |
435 // cache and return loop information for this block | |
436 _loop_map.at_put(block_id, loop_state); | |
437 return loop_state; | |
438 } | |
439 | |
440 | |
441 #ifndef PRODUCT | |
442 | |
443 int compare_depth_first(BlockBegin** a, BlockBegin** b) { | |
444 return (*a)->depth_first_number() - (*b)->depth_first_number(); | |
445 } | |
446 | |
447 void BlockListBuilder::print() { | |
448 tty->print("----- initial block list of BlockListBuilder for method "); | |
449 method()->print_short_name(); | |
450 tty->cr(); | |
451 | |
452 // better readability if blocks are sorted in processing order | |
453 _blocks.sort(compare_depth_first); | |
454 | |
455 for (int i = 0; i < _blocks.length(); i++) { | |
456 BlockBegin* cur = _blocks.at(i); | |
457 tty->print("%4d: B%-4d bci: %-4d preds: %-4d ", cur->depth_first_number(), cur->block_id(), cur->bci(), cur->total_preds()); | |
458 | |
459 tty->print(cur->is_set(BlockBegin::std_entry_flag) ? " std" : " "); | |
460 tty->print(cur->is_set(BlockBegin::osr_entry_flag) ? " osr" : " "); | |
461 tty->print(cur->is_set(BlockBegin::exception_entry_flag) ? " ex" : " "); | |
462 tty->print(cur->is_set(BlockBegin::subroutine_entry_flag) ? " sr" : " "); | |
463 tty->print(cur->is_set(BlockBegin::parser_loop_header_flag) ? " lh" : " "); | |
464 | |
465 if (cur->number_of_sux() > 0) { | |
466 tty->print(" sux: "); | |
467 for (int j = 0; j < cur->number_of_sux(); j++) { | |
468 BlockBegin* sux = cur->sux_at(j); | |
469 tty->print("B%d ", sux->block_id()); | |
470 } | |
471 } | |
472 tty->cr(); | |
473 } | |
474 } | |
475 | |
476 #endif | |
477 | |
478 | |
479 // A simple growable array of Values indexed by ciFields | |
480 class FieldBuffer: public CompilationResourceObj { | |
481 private: | |
482 GrowableArray<Value> _values; | |
483 | |
484 public: | |
485 FieldBuffer() {} | |
486 | |
487 void kill() { | |
488 _values.trunc_to(0); | |
489 } | |
490 | |
491 Value at(ciField* field) { | |
492 assert(field->holder()->is_loaded(), "must be a loaded field"); | |
493 int offset = field->offset(); | |
494 if (offset < _values.length()) { | |
495 return _values.at(offset); | |
496 } else { | |
497 return NULL; | |
498 } | |
499 } | |
500 | |
501 void at_put(ciField* field, Value value) { | |
502 assert(field->holder()->is_loaded(), "must be a loaded field"); | |
503 int offset = field->offset(); | |
504 _values.at_put_grow(offset, value, NULL); | |
505 } | |
506 | |
507 }; | |
508 | |
509 | |
510 // MemoryBuffer is fairly simple model of the current state of memory. | |
511 // It partitions memory into several pieces. The first piece is | |
512 // generic memory where little is known about the owner of the memory. | |
513 // This is conceptually represented by the tuple <O, F, V> which says | |
514 // that the field F of object O has value V. This is flattened so | |
515 // that F is represented by the offset of the field and the parallel | |
516 // arrays _objects and _values are used for O and V. Loads of O.F can | |
517 // simply use V. Newly allocated objects are kept in a separate list | |
518 // along with a parallel array for each object which represents the | |
519 // current value of its fields. Stores of the default value to fields | |
520 // which have never been stored to before are eliminated since they | |
521 // are redundant. Once newly allocated objects are stored into | |
522 // another object or they are passed out of the current compile they | |
523 // are treated like generic memory. | |
524 | |
525 class MemoryBuffer: public CompilationResourceObj { | |
526 private: | |
527 FieldBuffer _values; | |
528 GrowableArray<Value> _objects; | |
529 GrowableArray<Value> _newobjects; | |
530 GrowableArray<FieldBuffer*> _fields; | |
531 | |
532 public: | |
533 MemoryBuffer() {} | |
534 | |
535 StoreField* store(StoreField* st) { | |
536 if (!EliminateFieldAccess) { | |
537 return st; | |
538 } | |
539 | |
540 Value object = st->obj(); | |
541 Value value = st->value(); | |
542 ciField* field = st->field(); | |
543 if (field->holder()->is_loaded()) { | |
544 int offset = field->offset(); | |
545 int index = _newobjects.find(object); | |
546 if (index != -1) { | |
547 // newly allocated object with no other stores performed on this field | |
548 FieldBuffer* buf = _fields.at(index); | |
549 if (buf->at(field) == NULL && is_default_value(value)) { | |
550 #ifndef PRODUCT | |
551 if (PrintIRDuringConstruction && Verbose) { | |
552 tty->print_cr("Eliminated store for object %d:", index); | |
553 st->print_line(); | |
554 } | |
555 #endif | |
556 return NULL; | |
557 } else { | |
558 buf->at_put(field, value); | |
559 } | |
560 } else { | |
561 _objects.at_put_grow(offset, object, NULL); | |
562 _values.at_put(field, value); | |
563 } | |
564 | |
565 store_value(value); | |
566 } else { | |
567 // if we held onto field names we could alias based on names but | |
568 // we don't know what's being stored to so kill it all. | |
569 kill(); | |
570 } | |
571 return st; | |
572 } | |
573 | |
574 | |
575 // return true if this value correspond to the default value of a field. | |
576 bool is_default_value(Value value) { | |
577 Constant* con = value->as_Constant(); | |
578 if (con) { | |
579 switch (con->type()->tag()) { | |
580 case intTag: return con->type()->as_IntConstant()->value() == 0; | |
581 case longTag: return con->type()->as_LongConstant()->value() == 0; | |
582 case floatTag: return jint_cast(con->type()->as_FloatConstant()->value()) == 0; | |
583 case doubleTag: return jlong_cast(con->type()->as_DoubleConstant()->value()) == jlong_cast(0); | |
584 case objectTag: return con->type() == objectNull; | |
585 default: ShouldNotReachHere(); | |
586 } | |
587 } | |
588 return false; | |
589 } | |
590 | |
591 | |
592 // return either the actual value of a load or the load itself | |
593 Value load(LoadField* load) { | |
594 if (!EliminateFieldAccess) { | |
595 return load; | |
596 } | |
597 | |
598 if (RoundFPResults && UseSSE < 2 && load->type()->is_float_kind()) { | |
599 // can't skip load since value might get rounded as a side effect | |
600 return load; | |
601 } | |
602 | |
603 ciField* field = load->field(); | |
604 Value object = load->obj(); | |
605 if (field->holder()->is_loaded() && !field->is_volatile()) { | |
606 int offset = field->offset(); | |
607 Value result = NULL; | |
608 int index = _newobjects.find(object); | |
609 if (index != -1) { | |
610 result = _fields.at(index)->at(field); | |
611 } else if (_objects.at_grow(offset, NULL) == object) { | |
612 result = _values.at(field); | |
613 } | |
614 if (result != NULL) { | |
615 #ifndef PRODUCT | |
616 if (PrintIRDuringConstruction && Verbose) { | |
617 tty->print_cr("Eliminated load: "); | |
618 load->print_line(); | |
619 } | |
620 #endif | |
621 assert(result->type()->tag() == load->type()->tag(), "wrong types"); | |
622 return result; | |
623 } | |
624 } | |
625 return load; | |
626 } | |
627 | |
628 // Record this newly allocated object | |
629 void new_instance(NewInstance* object) { | |
630 int index = _newobjects.length(); | |
631 _newobjects.append(object); | |
632 if (_fields.at_grow(index, NULL) == NULL) { | |
633 _fields.at_put(index, new FieldBuffer()); | |
634 } else { | |
635 _fields.at(index)->kill(); | |
636 } | |
637 } | |
638 | |
639 void store_value(Value value) { | |
640 int index = _newobjects.find(value); | |
641 if (index != -1) { | |
642 // stored a newly allocated object into another object. | |
643 // Assume we've lost track of it as separate slice of memory. | |
644 // We could do better by keeping track of whether individual | |
645 // fields could alias each other. | |
646 _newobjects.remove_at(index); | |
647 // pull out the field info and store it at the end up the list | |
648 // of field info list to be reused later. | |
649 _fields.append(_fields.at(index)); | |
650 _fields.remove_at(index); | |
651 } | |
652 } | |
653 | |
654 void kill() { | |
655 _newobjects.trunc_to(0); | |
656 _objects.trunc_to(0); | |
657 _values.kill(); | |
658 } | |
659 }; | |
660 | |
661 | |
662 // Implementation of GraphBuilder's ScopeData | |
663 | |
664 GraphBuilder::ScopeData::ScopeData(ScopeData* parent) | |
665 : _parent(parent) | |
666 , _bci2block(NULL) | |
667 , _scope(NULL) | |
668 , _has_handler(false) | |
669 , _stream(NULL) | |
670 , _work_list(NULL) | |
671 , _parsing_jsr(false) | |
672 , _jsr_xhandlers(NULL) | |
673 , _caller_stack_size(-1) | |
674 , _continuation(NULL) | |
675 , _num_returns(0) | |
676 , _cleanup_block(NULL) | |
677 , _cleanup_return_prev(NULL) | |
678 , _cleanup_state(NULL) | |
679 { | |
680 if (parent != NULL) { | |
681 _max_inline_size = (intx) ((float) NestedInliningSizeRatio * (float) parent->max_inline_size() / 100.0f); | |
682 } else { | |
683 _max_inline_size = MaxInlineSize; | |
684 } | |
685 if (_max_inline_size < MaxTrivialSize) { | |
686 _max_inline_size = MaxTrivialSize; | |
687 } | |
688 } | |
689 | |
690 | |
691 void GraphBuilder::kill_all() { | |
692 if (UseLocalValueNumbering) { | |
693 vmap()->kill_all(); | |
694 } | |
695 _memory->kill(); | |
696 } | |
697 | |
698 | |
699 BlockBegin* GraphBuilder::ScopeData::block_at(int bci) { | |
700 if (parsing_jsr()) { | |
701 // It is necessary to clone all blocks associated with a | |
702 // subroutine, including those for exception handlers in the scope | |
703 // of the method containing the jsr (because those exception | |
704 // handlers may contain ret instructions in some cases). | |
705 BlockBegin* block = bci2block()->at(bci); | |
706 if (block != NULL && block == parent()->bci2block()->at(bci)) { | |
707 BlockBegin* new_block = new BlockBegin(block->bci()); | |
708 #ifndef PRODUCT | |
709 if (PrintInitialBlockList) { | |
710 tty->print_cr("CFG: cloned block %d (bci %d) as block %d for jsr", | |
711 block->block_id(), block->bci(), new_block->block_id()); | |
712 } | |
713 #endif | |
714 // copy data from cloned blocked | |
715 new_block->set_depth_first_number(block->depth_first_number()); | |
716 if (block->is_set(BlockBegin::parser_loop_header_flag)) new_block->set(BlockBegin::parser_loop_header_flag); | |
717 // Preserve certain flags for assertion checking | |
718 if (block->is_set(BlockBegin::subroutine_entry_flag)) new_block->set(BlockBegin::subroutine_entry_flag); | |
719 if (block->is_set(BlockBegin::exception_entry_flag)) new_block->set(BlockBegin::exception_entry_flag); | |
720 | |
721 // copy was_visited_flag to allow early detection of bailouts | |
722 // if a block that is used in a jsr has already been visited before, | |
723 // it is shared between the normal control flow and a subroutine | |
724 // BlockBegin::try_merge returns false when the flag is set, this leads | |
725 // to a compilation bailout | |
726 if (block->is_set(BlockBegin::was_visited_flag)) new_block->set(BlockBegin::was_visited_flag); | |
727 | |
728 bci2block()->at_put(bci, new_block); | |
729 block = new_block; | |
730 } | |
731 return block; | |
732 } else { | |
733 return bci2block()->at(bci); | |
734 } | |
735 } | |
736 | |
737 | |
738 XHandlers* GraphBuilder::ScopeData::xhandlers() const { | |
739 if (_jsr_xhandlers == NULL) { | |
740 assert(!parsing_jsr(), ""); | |
741 return scope()->xhandlers(); | |
742 } | |
743 assert(parsing_jsr(), ""); | |
744 return _jsr_xhandlers; | |
745 } | |
746 | |
747 | |
748 void GraphBuilder::ScopeData::set_scope(IRScope* scope) { | |
749 _scope = scope; | |
750 bool parent_has_handler = false; | |
751 if (parent() != NULL) { | |
752 parent_has_handler = parent()->has_handler(); | |
753 } | |
754 _has_handler = parent_has_handler || scope->xhandlers()->has_handlers(); | |
755 } | |
756 | |
757 | |
758 void GraphBuilder::ScopeData::set_inline_cleanup_info(BlockBegin* block, | |
759 Instruction* return_prev, | |
760 ValueStack* return_state) { | |
761 _cleanup_block = block; | |
762 _cleanup_return_prev = return_prev; | |
763 _cleanup_state = return_state; | |
764 } | |
765 | |
766 | |
767 void GraphBuilder::ScopeData::add_to_work_list(BlockBegin* block) { | |
768 if (_work_list == NULL) { | |
769 _work_list = new BlockList(); | |
770 } | |
771 | |
772 if (!block->is_set(BlockBegin::is_on_work_list_flag)) { | |
773 // Do not start parsing the continuation block while in a | |
774 // sub-scope | |
775 if (parsing_jsr()) { | |
776 if (block == jsr_continuation()) { | |
777 return; | |
778 } | |
779 } else { | |
780 if (block == continuation()) { | |
781 return; | |
782 } | |
783 } | |
784 block->set(BlockBegin::is_on_work_list_flag); | |
785 _work_list->push(block); | |
786 | |
787 sort_top_into_worklist(_work_list, block); | |
788 } | |
789 } | |
790 | |
791 | |
792 void GraphBuilder::sort_top_into_worklist(BlockList* worklist, BlockBegin* top) { | |
793 assert(worklist->top() == top, ""); | |
794 // sort block descending into work list | |
795 const int dfn = top->depth_first_number(); | |
796 assert(dfn != -1, "unknown depth first number"); | |
797 int i = worklist->length()-2; | |
798 while (i >= 0) { | |
799 BlockBegin* b = worklist->at(i); | |
800 if (b->depth_first_number() < dfn) { | |
801 worklist->at_put(i+1, b); | |
802 } else { | |
803 break; | |
804 } | |
805 i --; | |
806 } | |
807 if (i >= -1) worklist->at_put(i + 1, top); | |
808 } | |
809 | |
810 | |
811 BlockBegin* GraphBuilder::ScopeData::remove_from_work_list() { | |
812 if (is_work_list_empty()) { | |
813 return NULL; | |
814 } | |
815 return _work_list->pop(); | |
816 } | |
817 | |
818 | |
819 bool GraphBuilder::ScopeData::is_work_list_empty() const { | |
820 return (_work_list == NULL || _work_list->length() == 0); | |
821 } | |
822 | |
823 | |
824 void GraphBuilder::ScopeData::setup_jsr_xhandlers() { | |
825 assert(parsing_jsr(), ""); | |
826 // clone all the exception handlers from the scope | |
827 XHandlers* handlers = new XHandlers(scope()->xhandlers()); | |
828 const int n = handlers->length(); | |
829 for (int i = 0; i < n; i++) { | |
830 // The XHandlers need to be adjusted to dispatch to the cloned | |
831 // handler block instead of the default one but the synthetic | |
832 // unlocker needs to be handled specially. The synthetic unlocker | |
833 // should be left alone since there can be only one and all code | |
834 // should dispatch to the same one. | |
835 XHandler* h = handlers->handler_at(i); | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1295
diff
changeset
|
836 assert(h->handler_bci() != SynchronizationEntryBCI, "must be real"); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1295
diff
changeset
|
837 h->set_entry_block(block_at(h->handler_bci())); |
0 | 838 } |
839 _jsr_xhandlers = handlers; | |
840 } | |
841 | |
842 | |
843 int GraphBuilder::ScopeData::num_returns() { | |
844 if (parsing_jsr()) { | |
845 return parent()->num_returns(); | |
846 } | |
847 return _num_returns; | |
848 } | |
849 | |
850 | |
851 void GraphBuilder::ScopeData::incr_num_returns() { | |
852 if (parsing_jsr()) { | |
853 parent()->incr_num_returns(); | |
854 } else { | |
855 ++_num_returns; | |
856 } | |
857 } | |
858 | |
859 | |
860 // Implementation of GraphBuilder | |
861 | |
862 #define INLINE_BAILOUT(msg) { inline_bailout(msg); return false; } | |
863 | |
864 | |
865 void GraphBuilder::load_constant() { | |
866 ciConstant con = stream()->get_constant(); | |
867 if (con.basic_type() == T_ILLEGAL) { | |
868 BAILOUT("could not resolve a constant"); | |
869 } else { | |
870 ValueType* t = illegalType; | |
871 ValueStack* patch_state = NULL; | |
872 switch (con.basic_type()) { | |
873 case T_BOOLEAN: t = new IntConstant (con.as_boolean()); break; | |
874 case T_BYTE : t = new IntConstant (con.as_byte ()); break; | |
875 case T_CHAR : t = new IntConstant (con.as_char ()); break; | |
876 case T_SHORT : t = new IntConstant (con.as_short ()); break; | |
877 case T_INT : t = new IntConstant (con.as_int ()); break; | |
878 case T_LONG : t = new LongConstant (con.as_long ()); break; | |
879 case T_FLOAT : t = new FloatConstant (con.as_float ()); break; | |
880 case T_DOUBLE : t = new DoubleConstant (con.as_double ()); break; | |
881 case T_ARRAY : t = new ArrayConstant (con.as_object ()->as_array ()); break; | |
882 case T_OBJECT : | |
883 { | |
884 ciObject* obj = con.as_object(); | |
1602 | 885 if (!obj->is_loaded() |
886 || (PatchALot && obj->klass() != ciEnv::current()->String_klass())) { | |
1819 | 887 patch_state = copy_state_before(); |
1602 | 888 t = new ObjectConstant(obj); |
0 | 889 } else { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
890 assert(obj->is_instance(), "must be java_mirror of klass"); |
0 | 891 t = new InstanceConstant(obj->as_instance()); |
892 } | |
893 break; | |
894 } | |
895 default : ShouldNotReachHere(); | |
896 } | |
897 Value x; | |
898 if (patch_state != NULL) { | |
899 x = new Constant(t, patch_state); | |
900 } else { | |
901 x = new Constant(t); | |
902 } | |
903 push(t, append(x)); | |
904 } | |
905 } | |
906 | |
907 | |
908 void GraphBuilder::load_local(ValueType* type, int index) { | |
1819 | 909 Value x = state()->local_at(index); |
910 assert(x != NULL && !x->type()->is_illegal(), "access of illegal local variable"); | |
0 | 911 push(type, x); |
912 } | |
913 | |
914 | |
915 void GraphBuilder::store_local(ValueType* type, int index) { | |
916 Value x = pop(type); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
917 store_local(state(), x, index); |
0 | 918 } |
919 | |
920 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
921 void GraphBuilder::store_local(ValueStack* state, Value x, int index) { |
0 | 922 if (parsing_jsr()) { |
923 // We need to do additional tracking of the location of the return | |
924 // address for jsrs since we don't handle arbitrary jsr/ret | |
925 // constructs. Here we are figuring out in which circumstances we | |
926 // need to bail out. | |
927 if (x->type()->is_address()) { | |
928 scope_data()->set_jsr_return_address_local(index); | |
929 | |
930 // Also check parent jsrs (if any) at this time to see whether | |
931 // they are using this local. We don't handle skipping over a | |
932 // ret. | |
933 for (ScopeData* cur_scope_data = scope_data()->parent(); | |
934 cur_scope_data != NULL && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope(); | |
935 cur_scope_data = cur_scope_data->parent()) { | |
936 if (cur_scope_data->jsr_return_address_local() == index) { | |
937 BAILOUT("subroutine overwrites return address from previous subroutine"); | |
938 } | |
939 } | |
940 } else if (index == scope_data()->jsr_return_address_local()) { | |
941 scope_data()->set_jsr_return_address_local(-1); | |
942 } | |
943 } | |
944 | |
945 state->store_local(index, round_fp(x)); | |
946 } | |
947 | |
948 | |
949 void GraphBuilder::load_indexed(BasicType type) { | |
8860 | 950 // In case of in block code motion in range check elimination |
951 ValueStack* state_before = copy_state_indexed_access(); | |
952 compilation()->set_has_access_indexed(true); | |
0 | 953 Value index = ipop(); |
954 Value array = apop(); | |
955 Value length = NULL; | |
956 if (CSEArrayLength || | |
957 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || | |
958 (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { | |
1819 | 959 length = append(new ArrayLength(array, state_before)); |
0 | 960 } |
1819 | 961 push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before))); |
0 | 962 } |
963 | |
964 | |
965 void GraphBuilder::store_indexed(BasicType type) { | |
8860 | 966 // In case of in block code motion in range check elimination |
967 ValueStack* state_before = copy_state_indexed_access(); | |
968 compilation()->set_has_access_indexed(true); | |
0 | 969 Value value = pop(as_ValueType(type)); |
970 Value index = ipop(); | |
971 Value array = apop(); | |
972 Value length = NULL; | |
973 if (CSEArrayLength || | |
974 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || | |
975 (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { | |
1819 | 976 length = append(new ArrayLength(array, state_before)); |
0 | 977 } |
1819 | 978 StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); |
0 | 979 append(result); |
459 | 980 _memory->store_value(value); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
981 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
982 if (type == T_OBJECT && is_profiling()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
983 // Note that we'd collect profile data in this method if we wanted it. |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
984 compilation()->set_would_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
985 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
986 if (profile_checkcasts()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
987 result->set_profiled_method(method()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
988 result->set_profiled_bci(bci()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
989 result->set_should_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
990 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
991 } |
0 | 992 } |
993 | |
994 | |
995 void GraphBuilder::stack_op(Bytecodes::Code code) { | |
996 switch (code) { | |
997 case Bytecodes::_pop: | |
998 { state()->raw_pop(); | |
999 } | |
1000 break; | |
1001 case Bytecodes::_pop2: | |
1002 { state()->raw_pop(); | |
1003 state()->raw_pop(); | |
1004 } | |
1005 break; | |
1006 case Bytecodes::_dup: | |
1007 { Value w = state()->raw_pop(); | |
1008 state()->raw_push(w); | |
1009 state()->raw_push(w); | |
1010 } | |
1011 break; | |
1012 case Bytecodes::_dup_x1: | |
1013 { Value w1 = state()->raw_pop(); | |
1014 Value w2 = state()->raw_pop(); | |
1015 state()->raw_push(w1); | |
1016 state()->raw_push(w2); | |
1017 state()->raw_push(w1); | |
1018 } | |
1019 break; | |
1020 case Bytecodes::_dup_x2: | |
1021 { Value w1 = state()->raw_pop(); | |
1022 Value w2 = state()->raw_pop(); | |
1023 Value w3 = state()->raw_pop(); | |
1024 state()->raw_push(w1); | |
1025 state()->raw_push(w3); | |
1026 state()->raw_push(w2); | |
1027 state()->raw_push(w1); | |
1028 } | |
1029 break; | |
1030 case Bytecodes::_dup2: | |
1031 { Value w1 = state()->raw_pop(); | |
1032 Value w2 = state()->raw_pop(); | |
1033 state()->raw_push(w2); | |
1034 state()->raw_push(w1); | |
1035 state()->raw_push(w2); | |
1036 state()->raw_push(w1); | |
1037 } | |
1038 break; | |
1039 case Bytecodes::_dup2_x1: | |
1040 { Value w1 = state()->raw_pop(); | |
1041 Value w2 = state()->raw_pop(); | |
1042 Value w3 = state()->raw_pop(); | |
1043 state()->raw_push(w2); | |
1044 state()->raw_push(w1); | |
1045 state()->raw_push(w3); | |
1046 state()->raw_push(w2); | |
1047 state()->raw_push(w1); | |
1048 } | |
1049 break; | |
1050 case Bytecodes::_dup2_x2: | |
1051 { Value w1 = state()->raw_pop(); | |
1052 Value w2 = state()->raw_pop(); | |
1053 Value w3 = state()->raw_pop(); | |
1054 Value w4 = state()->raw_pop(); | |
1055 state()->raw_push(w2); | |
1056 state()->raw_push(w1); | |
1057 state()->raw_push(w4); | |
1058 state()->raw_push(w3); | |
1059 state()->raw_push(w2); | |
1060 state()->raw_push(w1); | |
1061 } | |
1062 break; | |
1063 case Bytecodes::_swap: | |
1064 { Value w1 = state()->raw_pop(); | |
1065 Value w2 = state()->raw_pop(); | |
1066 state()->raw_push(w1); | |
1067 state()->raw_push(w2); | |
1068 } | |
1069 break; | |
1070 default: | |
1071 ShouldNotReachHere(); | |
1072 break; | |
1073 } | |
1074 } | |
1075 | |
1076 | |
1819 | 1077 void GraphBuilder::arithmetic_op(ValueType* type, Bytecodes::Code code, ValueStack* state_before) { |
0 | 1078 Value y = pop(type); |
1079 Value x = pop(type); | |
1080 // NOTE: strictfp can be queried from current method since we don't | |
1081 // inline methods with differing strictfp bits | |
1819 | 1082 Value res = new ArithmeticOp(code, x, y, method()->is_strict(), state_before); |
0 | 1083 // Note: currently single-precision floating-point rounding on Intel is handled at the LIRGenerator level |
1084 res = append(res); | |
1085 if (method()->is_strict()) { | |
1086 res = round_fp(res); | |
1087 } | |
1088 push(type, res); | |
1089 } | |
1090 | |
1091 | |
1092 void GraphBuilder::negate_op(ValueType* type) { | |
1093 push(type, append(new NegateOp(pop(type)))); | |
1094 } | |
1095 | |
1096 | |
1097 void GraphBuilder::shift_op(ValueType* type, Bytecodes::Code code) { | |
1098 Value s = ipop(); | |
1099 Value x = pop(type); | |
1100 // try to simplify | |
1101 // Note: This code should go into the canonicalizer as soon as it can | |
1102 // can handle canonicalized forms that contain more than one node. | |
1103 if (CanonicalizeNodes && code == Bytecodes::_iushr) { | |
1104 // pattern: x >>> s | |
1105 IntConstant* s1 = s->type()->as_IntConstant(); | |
1106 if (s1 != NULL) { | |
1107 // pattern: x >>> s1, with s1 constant | |
1108 ShiftOp* l = x->as_ShiftOp(); | |
1109 if (l != NULL && l->op() == Bytecodes::_ishl) { | |
1110 // pattern: (a << b) >>> s1 | |
1111 IntConstant* s0 = l->y()->type()->as_IntConstant(); | |
1112 if (s0 != NULL) { | |
1113 // pattern: (a << s0) >>> s1 | |
1114 const int s0c = s0->value() & 0x1F; // only the low 5 bits are significant for shifts | |
1115 const int s1c = s1->value() & 0x1F; // only the low 5 bits are significant for shifts | |
1116 if (s0c == s1c) { | |
1117 if (s0c == 0) { | |
1118 // pattern: (a << 0) >>> 0 => simplify to: a | |
1119 ipush(l->x()); | |
1120 } else { | |
1121 // pattern: (a << s0c) >>> s0c => simplify to: a & m, with m constant | |
1122 assert(0 < s0c && s0c < BitsPerInt, "adjust code below to handle corner cases"); | |
1123 const int m = (1 << (BitsPerInt - s0c)) - 1; | |
1124 Value s = append(new Constant(new IntConstant(m))); | |
1125 ipush(append(new LogicOp(Bytecodes::_iand, l->x(), s))); | |
1126 } | |
1127 return; | |
1128 } | |
1129 } | |
1130 } | |
1131 } | |
1132 } | |
1133 // could not simplify | |
1134 push(type, append(new ShiftOp(code, x, s))); | |
1135 } | |
1136 | |
1137 | |
1138 void GraphBuilder::logic_op(ValueType* type, Bytecodes::Code code) { | |
1139 Value y = pop(type); | |
1140 Value x = pop(type); | |
1141 push(type, append(new LogicOp(code, x, y))); | |
1142 } | |
1143 | |
1144 | |
1145 void GraphBuilder::compare_op(ValueType* type, Bytecodes::Code code) { | |
1819 | 1146 ValueStack* state_before = copy_state_before(); |
0 | 1147 Value y = pop(type); |
1148 Value x = pop(type); | |
1149 ipush(append(new CompareOp(code, x, y, state_before))); | |
1150 } | |
1151 | |
1152 | |
1153 void GraphBuilder::convert(Bytecodes::Code op, BasicType from, BasicType to) { | |
1154 push(as_ValueType(to), append(new Convert(op, pop(as_ValueType(from)), as_ValueType(to)))); | |
1155 } | |
1156 | |
1157 | |
1158 void GraphBuilder::increment() { | |
1159 int index = stream()->get_index(); | |
1160 int delta = stream()->is_wide() ? (signed short)Bytes::get_Java_u2(stream()->cur_bcp() + 4) : (signed char)(stream()->cur_bcp()[2]); | |
1161 load_local(intType, index); | |
1162 ipush(append(new Constant(new IntConstant(delta)))); | |
1163 arithmetic_op(intType, Bytecodes::_iadd); | |
1164 store_local(intType, index); | |
1165 } | |
1166 | |
1167 | |
1168 void GraphBuilder::_goto(int from_bci, int to_bci) { | |
1783 | 1169 Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci); |
1170 if (is_profiling()) { | |
1171 compilation()->set_would_profile(true); | |
1172 x->set_profiled_bci(bci()); | |
3997
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1173 if (profile_branches()) { |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1174 x->set_profiled_method(method()); |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1175 x->set_should_profile(true); |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1176 } |
1783 | 1177 } |
1178 append(x); | |
0 | 1179 } |
1180 | |
1181 | |
1182 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) { | |
1183 BlockBegin* tsux = block_at(stream()->get_dest()); | |
1184 BlockBegin* fsux = block_at(stream()->next_bci()); | |
1185 bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci(); | |
8860 | 1186 // In case of loop invariant code motion or predicate insertion |
1187 // before the body of a loop the state is needed | |
1188 Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : NULL, is_bb)); | |
1783 | 1189 |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1190 assert(i->as_Goto() == NULL || |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1191 (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) || |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1192 (i->as_Goto()->sux_at(0) == fsux && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()), |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1193 "safepoint state of Goto returned by canonicalizer incorrect"); |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1194 |
1783 | 1195 if (is_profiling()) { |
1196 If* if_node = i->as_If(); | |
1197 if (if_node != NULL) { | |
1198 // Note that we'd collect profile data in this method if we wanted it. | |
1199 compilation()->set_would_profile(true); | |
1200 // At level 2 we need the proper bci to count backedges | |
1201 if_node->set_profiled_bci(bci()); | |
1202 if (profile_branches()) { | |
1203 // Successors can be rotated by the canonicalizer, check for this case. | |
1204 if_node->set_profiled_method(method()); | |
1205 if_node->set_should_profile(true); | |
1206 if (if_node->tsux() == fsux) { | |
1207 if_node->set_swapped(true); | |
1208 } | |
1209 } | |
1210 return; | |
1211 } | |
1212 | |
1213 // Check if this If was reduced to Goto. | |
1214 Goto *goto_node = i->as_Goto(); | |
1215 if (goto_node != NULL) { | |
1216 compilation()->set_would_profile(true); | |
3997
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1217 goto_node->set_profiled_bci(bci()); |
1783 | 1218 if (profile_branches()) { |
1219 goto_node->set_profiled_method(method()); | |
1220 goto_node->set_should_profile(true); | |
1221 // Find out which successor is used. | |
1222 if (goto_node->default_sux() == tsux) { | |
1223 goto_node->set_direction(Goto::taken); | |
1224 } else if (goto_node->default_sux() == fsux) { | |
1225 goto_node->set_direction(Goto::not_taken); | |
1226 } else { | |
1227 ShouldNotReachHere(); | |
1228 } | |
1229 } | |
1230 return; | |
1231 } | |
0 | 1232 } |
1233 } | |
1234 | |
1235 | |
1236 void GraphBuilder::if_zero(ValueType* type, If::Condition cond) { | |
1237 Value y = append(new Constant(intZero)); | |
1819 | 1238 ValueStack* state_before = copy_state_before(); |
0 | 1239 Value x = ipop(); |
1240 if_node(x, cond, y, state_before); | |
1241 } | |
1242 | |
1243 | |
1244 void GraphBuilder::if_null(ValueType* type, If::Condition cond) { | |
1245 Value y = append(new Constant(objectNull)); | |
1819 | 1246 ValueStack* state_before = copy_state_before(); |
0 | 1247 Value x = apop(); |
1248 if_node(x, cond, y, state_before); | |
1249 } | |
1250 | |
1251 | |
1252 void GraphBuilder::if_same(ValueType* type, If::Condition cond) { | |
1819 | 1253 ValueStack* state_before = copy_state_before(); |
0 | 1254 Value y = pop(type); |
1255 Value x = pop(type); | |
1256 if_node(x, cond, y, state_before); | |
1257 } | |
1258 | |
1259 | |
1260 void GraphBuilder::jsr(int dest) { | |
1261 // We only handle well-formed jsrs (those which are "block-structured"). | |
1262 // If the bytecodes are strange (jumping out of a jsr block) then we | |
1263 // might end up trying to re-parse a block containing a jsr which | |
1264 // has already been activated. Watch for this case and bail out. | |
1265 for (ScopeData* cur_scope_data = scope_data(); | |
1266 cur_scope_data != NULL && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope(); | |
1267 cur_scope_data = cur_scope_data->parent()) { | |
1268 if (cur_scope_data->jsr_entry_bci() == dest) { | |
1269 BAILOUT("too-complicated jsr/ret structure"); | |
1270 } | |
1271 } | |
1272 | |
1273 push(addressType, append(new Constant(new AddressConstant(next_bci())))); | |
1274 if (!try_inline_jsr(dest)) { | |
1275 return; // bailed out while parsing and inlining subroutine | |
1276 } | |
1277 } | |
1278 | |
1279 | |
1280 void GraphBuilder::ret(int local_index) { | |
1281 if (!parsing_jsr()) BAILOUT("ret encountered while not parsing subroutine"); | |
1282 | |
1283 if (local_index != scope_data()->jsr_return_address_local()) { | |
1284 BAILOUT("can not handle complicated jsr/ret constructs"); | |
1285 } | |
1286 | |
1287 // Rets simply become (NON-SAFEPOINT) gotos to the jsr continuation | |
1288 append(new Goto(scope_data()->jsr_continuation(), false)); | |
1289 } | |
1290 | |
1291 | |
1292 void GraphBuilder::table_switch() { | |
2142 | 1293 Bytecode_tableswitch sw(stream()); |
1294 const int l = sw.length(); | |
0 | 1295 if (CanonicalizeNodes && l == 1) { |
1296 // total of 2 successors => use If instead of switch | |
1297 // Note: This code should go into the canonicalizer as soon as it can | |
1298 // can handle canonicalized forms that contain more than one node. | |
2142 | 1299 Value key = append(new Constant(new IntConstant(sw.low_key()))); |
1300 BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0)); | |
1301 BlockBegin* fsux = block_at(bci() + sw.default_offset()); | |
0 | 1302 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); |
8860 | 1303 // In case of loop invariant code motion or predicate insertion |
1304 // before the body of a loop the state is needed | |
1305 ValueStack* state_before = copy_state_if_bb(is_bb); | |
0 | 1306 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); |
1307 } else { | |
1308 // collect successors | |
1309 BlockList* sux = new BlockList(l + 1, NULL); | |
1310 int i; | |
1311 bool has_bb = false; | |
1312 for (i = 0; i < l; i++) { | |
2142 | 1313 sux->at_put(i, block_at(bci() + sw.dest_offset_at(i))); |
1314 if (sw.dest_offset_at(i) < 0) has_bb = true; | |
0 | 1315 } |
1316 // add default successor | |
5925
4fabc16dc5bf
6910464: Lookupswitch and Tableswitch default branches not recognized as safepoints
roland
parents:
4943
diff
changeset
|
1317 if (sw.default_offset() < 0) has_bb = true; |
2142 | 1318 sux->at_put(i, block_at(bci() + sw.default_offset())); |
8860 | 1319 // In case of loop invariant code motion or predicate insertion |
1320 // before the body of a loop the state is needed | |
1321 ValueStack* state_before = copy_state_if_bb(has_bb); | |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1322 Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1323 #ifdef ASSERT |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1324 if (res->as_Goto()) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1325 for (i = 0; i < l; i++) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1326 if (sux->at(i) == res->as_Goto()->sux_at(0)) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1327 assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect"); |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1328 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1329 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1330 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1331 #endif |
0 | 1332 } |
1333 } | |
1334 | |
1335 | |
1336 void GraphBuilder::lookup_switch() { | |
2142 | 1337 Bytecode_lookupswitch sw(stream()); |
1338 const int l = sw.number_of_pairs(); | |
0 | 1339 if (CanonicalizeNodes && l == 1) { |
1340 // total of 2 successors => use If instead of switch | |
1341 // Note: This code should go into the canonicalizer as soon as it can | |
1342 // can handle canonicalized forms that contain more than one node. | |
1343 // simplify to If | |
2142 | 1344 LookupswitchPair pair = sw.pair_at(0); |
1345 Value key = append(new Constant(new IntConstant(pair.match()))); | |
1346 BlockBegin* tsux = block_at(bci() + pair.offset()); | |
1347 BlockBegin* fsux = block_at(bci() + sw.default_offset()); | |
0 | 1348 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); |
8860 | 1349 // In case of loop invariant code motion or predicate insertion |
1350 // before the body of a loop the state is needed | |
1351 ValueStack* state_before = copy_state_if_bb(is_bb);; | |
0 | 1352 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); |
1353 } else { | |
1354 // collect successors & keys | |
1355 BlockList* sux = new BlockList(l + 1, NULL); | |
1356 intArray* keys = new intArray(l, 0); | |
1357 int i; | |
1358 bool has_bb = false; | |
1359 for (i = 0; i < l; i++) { | |
2142 | 1360 LookupswitchPair pair = sw.pair_at(i); |
1361 if (pair.offset() < 0) has_bb = true; | |
1362 sux->at_put(i, block_at(bci() + pair.offset())); | |
1363 keys->at_put(i, pair.match()); | |
0 | 1364 } |
1365 // add default successor | |
5925
4fabc16dc5bf
6910464: Lookupswitch and Tableswitch default branches not recognized as safepoints
roland
parents:
4943
diff
changeset
|
1366 if (sw.default_offset() < 0) has_bb = true; |
2142 | 1367 sux->at_put(i, block_at(bci() + sw.default_offset())); |
8860 | 1368 // In case of loop invariant code motion or predicate insertion |
1369 // before the body of a loop the state is needed | |
1370 ValueStack* state_before = copy_state_if_bb(has_bb); | |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1371 Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1372 #ifdef ASSERT |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1373 if (res->as_Goto()) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1374 for (i = 0; i < l; i++) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1375 if (sux->at(i) == res->as_Goto()->sux_at(0)) { |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1376 assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect"); |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1377 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1378 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1379 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1380 #endif |
0 | 1381 } |
1382 } | |
1383 | |
1384 void GraphBuilder::call_register_finalizer() { | |
1385 // If the receiver requires finalization then emit code to perform | |
1386 // the registration on return. | |
1387 | |
1388 // Gather some type information about the receiver | |
1819 | 1389 Value receiver = state()->local_at(0); |
0 | 1390 assert(receiver != NULL, "must have a receiver"); |
1391 ciType* declared_type = receiver->declared_type(); | |
1392 ciType* exact_type = receiver->exact_type(); | |
1393 if (exact_type == NULL && | |
1394 receiver->as_Local() && | |
1395 receiver->as_Local()->java_index() == 0) { | |
1396 ciInstanceKlass* ik = compilation()->method()->holder(); | |
1397 if (ik->is_final()) { | |
1398 exact_type = ik; | |
1399 } else if (UseCHA && !(ik->has_subklass() || ik->is_interface())) { | |
1400 // test class is leaf class | |
1401 compilation()->dependency_recorder()->assert_leaf_type(ik); | |
1402 exact_type = ik; | |
1403 } else { | |
1404 declared_type = ik; | |
1405 } | |
1406 } | |
1407 | |
1408 // see if we know statically that registration isn't required | |
1409 bool needs_check = true; | |
1410 if (exact_type != NULL) { | |
1411 needs_check = exact_type->as_instance_klass()->has_finalizer(); | |
1412 } else if (declared_type != NULL) { | |
1413 ciInstanceKlass* ik = declared_type->as_instance_klass(); | |
1414 if (!Dependencies::has_finalizable_subclass(ik)) { | |
1415 compilation()->dependency_recorder()->assert_has_no_finalizable_subclasses(ik); | |
1416 needs_check = false; | |
1417 } | |
1418 } | |
1419 | |
1420 if (needs_check) { | |
1421 // Perform the registration of finalizable objects. | |
1819 | 1422 ValueStack* state_before = copy_state_for_exception(); |
0 | 1423 load_local(objectType, 0); |
1424 append_split(new Intrinsic(voidType, vmIntrinsics::_Object_init, | |
1425 state()->pop_arguments(1), | |
1819 | 1426 true, state_before, true)); |
0 | 1427 } |
1428 } | |
1429 | |
1430 | |
1431 void GraphBuilder::method_return(Value x) { | |
1432 if (RegisterFinalizersAtInit && | |
1433 method()->intrinsic_id() == vmIntrinsics::_Object_init) { | |
1434 call_register_finalizer(); | |
1435 } | |
1436 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1437 bool need_mem_bar = false; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1438 if (method()->name() == ciSymbol::object_initializer_name() && |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1439 scope()->wrote_final()) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1440 need_mem_bar = true; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1441 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1442 |
0 | 1443 // Check to see whether we are inlining. If so, Return |
1444 // instructions become Gotos to the continuation point. | |
1445 if (continuation() != NULL) { | |
1446 assert(!method()->is_synchronized() || InlineSynchronizedMethods, "can not inline synchronized methods yet"); | |
1447 | |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1448 if (compilation()->env()->dtrace_method_probes()) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1449 // Report exit from inline methods |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1450 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
1451 args->push(append(new Constant(new MethodConstant(method())))); |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1452 append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args)); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1453 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1454 |
0 | 1455 // If the inlined method is synchronized, the monitor must be |
1456 // released before we jump to the continuation block. | |
1457 if (method()->is_synchronized()) { | |
1819 | 1458 assert(state()->locks_size() == 1, "receiver must be locked here"); |
1459 monitorexit(state()->lock_at(0), SynchronizationEntryBCI); | |
0 | 1460 } |
1461 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1462 if (need_mem_bar) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1463 append(new MemBar(lir_membar_storestore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1464 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1465 |
1819 | 1466 // State at end of inlined method is the state of the caller |
1467 // without the method parameters on stack, including the | |
1468 // return value, if any, of the inlined method on operand stack. | |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1469 int invoke_bci = state()->caller_state()->bci(); |
1819 | 1470 set_state(state()->caller_state()->copy_for_parsing()); |
0 | 1471 if (x != NULL) { |
1472 state()->push(x->type(), x); | |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1473 if (profile_return() && x->type()->is_object_kind()) { |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1474 ciMethod* caller = state()->scope()->method(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1475 ciMethodData* md = caller->method_data_or_null(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1476 ciProfileData* data = md->bci_to_data(invoke_bci); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1477 if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1478 bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1479 // May not be true in case of an inlined call through a method handle intrinsic. |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1480 if (has_return) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1481 profile_return_type(x, method(), caller, invoke_bci); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1482 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1483 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
1484 } |
0 | 1485 } |
1486 Goto* goto_callee = new Goto(continuation(), false); | |
1487 | |
1488 // See whether this is the first return; if so, store off some | |
1489 // of the state for later examination | |
1490 if (num_returns() == 0) { | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1491 set_inline_cleanup_info(); |
0 | 1492 } |
1493 | |
1494 // The current bci() is in the wrong scope, so use the bci() of | |
1495 // the continuation point. | |
1496 append_with_bci(goto_callee, scope_data()->continuation()->bci()); | |
1497 incr_num_returns(); | |
1498 return; | |
1499 } | |
1500 | |
1501 state()->truncate_stack(0); | |
1502 if (method()->is_synchronized()) { | |
1503 // perform the unlocking before exiting the method | |
1504 Value receiver; | |
1505 if (!method()->is_static()) { | |
1506 receiver = _initial_state->local_at(0); | |
1507 } else { | |
1508 receiver = append(new Constant(new ClassConstant(method()->holder()))); | |
1509 } | |
1510 append_split(new MonitorExit(receiver, state()->unlock())); | |
1511 } | |
1512 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1513 if (need_mem_bar) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1514 append(new MemBar(lir_membar_storestore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1515 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1516 |
0 | 1517 append(new Return(x)); |
1518 } | |
1519 | |
1520 | |
1521 void GraphBuilder::access_field(Bytecodes::Code code) { | |
1522 bool will_link; | |
1523 ciField* field = stream()->get_field(will_link); | |
1524 ciInstanceKlass* holder = field->holder(); | |
1525 BasicType field_type = field->type()->basic_type(); | |
1526 ValueType* type = as_ValueType(field_type); | |
1527 // call will_link again to determine if the field is valid. | |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1528 const bool needs_patching = !holder->is_loaded() || |
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1529 !field->will_link(method()->holder(), code) || |
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1530 PatchALot; |
0 | 1531 |
1819 | 1532 ValueStack* state_before = NULL; |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1533 if (!holder->is_initialized() || needs_patching) { |
0 | 1534 // save state before instruction for debug info when |
1535 // deoptimization happens during patching | |
1819 | 1536 state_before = copy_state_before(); |
0 | 1537 } |
1538 | |
1539 Value obj = NULL; | |
1540 if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) { | |
1819 | 1541 if (state_before != NULL) { |
0 | 1542 // build a patching constant |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2352
diff
changeset
|
1543 obj = new Constant(new InstanceConstant(holder->java_mirror()), state_before); |
0 | 1544 } else { |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2352
diff
changeset
|
1545 obj = new Constant(new InstanceConstant(holder->java_mirror())); |
0 | 1546 } |
1547 } | |
1548 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1549 if (field->is_final() && (code == Bytecodes::_putfield)) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1550 scope()->set_wrote_final(); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1551 } |
0 | 1552 |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1553 const int offset = !needs_patching ? field->offset() : -1; |
0 | 1554 switch (code) { |
1555 case Bytecodes::_getstatic: { | |
1556 // check for compile-time constants, i.e., initialized static final fields | |
1557 Instruction* constant = NULL; | |
1558 if (field->is_constant() && !PatchALot) { | |
1559 ciConstant field_val = field->constant_value(); | |
1560 BasicType field_type = field_val.basic_type(); | |
1561 switch (field_type) { | |
1562 case T_ARRAY: | |
1563 case T_OBJECT: | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
1564 if (field_val.as_object()->should_be_constant()) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1565 constant = new Constant(as_ValueType(field_val)); |
0 | 1566 } |
1567 break; | |
1568 | |
1569 default: | |
1570 constant = new Constant(as_ValueType(field_val)); | |
1571 } | |
18004
ee1c924763d2
8043546: C1 optimizes @Stable instance fields with default values
vlivanov
parents:
18003
diff
changeset
|
1572 // Stable static fields are checked for non-default values in ciField::initialize_from(). |
0 | 1573 } |
1574 if (constant != NULL) { | |
1575 push(type, append(constant)); | |
1576 } else { | |
1819 | 1577 if (state_before == NULL) { |
1578 state_before = copy_state_for_exception(); | |
1579 } | |
0 | 1580 push(type, append(new LoadField(append(obj), offset, field, true, |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1581 state_before, needs_patching))); |
0 | 1582 } |
1583 break; | |
1584 } | |
1585 case Bytecodes::_putstatic: | |
1586 { Value val = pop(type); | |
1819 | 1587 if (state_before == NULL) { |
1588 state_before = copy_state_for_exception(); | |
1589 } | |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1590 append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); |
0 | 1591 } |
1592 break; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1593 case Bytecodes::_getfield: { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1594 // Check for compile-time constants, i.e., trusted final non-static fields. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1595 Instruction* constant = NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1596 obj = apop(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1597 ObjectType* obj_type = obj->type()->as_ObjectType(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1598 if (obj_type->is_constant() && !PatchALot) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1599 ciObject* const_oop = obj_type->constant_value(); |
12165
59982ff9e0ec
8022283: Assertion failed: assert(is_loaded() && field->holder()->is_loaded() && klass()->is_subclass_of (field->holder())) failed: invalid access
rbackman
parents:
12160
diff
changeset
|
1600 if (!const_oop->is_null_object() && const_oop->is_loaded()) { |
6267
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1601 if (field->is_constant()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1602 ciConstant field_val = field->constant_value_of(const_oop); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1603 BasicType field_type = field_val.basic_type(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1604 switch (field_type) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1605 case T_ARRAY: |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1606 case T_OBJECT: |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1607 if (field_val.as_object()->should_be_constant()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1608 constant = new Constant(as_ValueType(field_val)); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1609 } |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1610 break; |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1611 default: |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1612 constant = new Constant(as_ValueType(field_val)); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1613 } |
18004
ee1c924763d2
8043546: C1 optimizes @Stable instance fields with default values
vlivanov
parents:
18003
diff
changeset
|
1614 if (FoldStableValues && field->is_stable() && field_val.is_null_or_zero()) { |
ee1c924763d2
8043546: C1 optimizes @Stable instance fields with default values
vlivanov
parents:
18003
diff
changeset
|
1615 // Stable field with default value can't be constant. |
ee1c924763d2
8043546: C1 optimizes @Stable instance fields with default values
vlivanov
parents:
18003
diff
changeset
|
1616 constant = NULL; |
ee1c924763d2
8043546: C1 optimizes @Stable instance fields with default values
vlivanov
parents:
18003
diff
changeset
|
1617 } |
6267
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1618 } else { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1619 // For CallSite objects treat the target field as a compile time constant. |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1620 if (const_oop->is_call_site()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1621 ciCallSite* call_site = const_oop->as_call_site(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1622 if (field->is_call_site_target()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1623 ciMethodHandle* target = call_site->get_target(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1624 if (target != NULL) { // just in case |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1625 ciConstant field_val(T_OBJECT, target); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1626 constant = new Constant(as_ValueType(field_val)); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1627 // Add a dependence for invalidation of the optimization. |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1628 if (!call_site->is_constant_call_site()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1629 dependency_recorder()->assert_call_site_target_value(call_site, target); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1630 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1631 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1632 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1633 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1634 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1635 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1636 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1637 if (constant != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1638 push(type, append(constant)); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1639 } else { |
1819 | 1640 if (state_before == NULL) { |
1641 state_before = copy_state_for_exception(); | |
1642 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1643 LoadField* load = new LoadField(obj, offset, field, false, state_before, needs_patching); |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2318
diff
changeset
|
1644 Value replacement = !needs_patching ? _memory->load(load) : load; |
0 | 1645 if (replacement != load) { |
1819 | 1646 assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); |
0 | 1647 push(type, replacement); |
1648 } else { | |
1649 push(type, append(load)); | |
1650 } | |
1651 } | |
1652 break; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1653 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1654 case Bytecodes::_putfield: { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1655 Value val = pop(type); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1656 obj = apop(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1657 if (state_before == NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1658 state_before = copy_state_for_exception(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1659 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1660 StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1661 if (!needs_patching) store = _memory->store(store); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1662 if (store != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1663 append(store); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1664 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1665 break; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1666 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1667 default: |
0 | 1668 ShouldNotReachHere(); |
1669 break; | |
1670 } | |
1671 } | |
1672 | |
1673 | |
1674 Dependencies* GraphBuilder::dependency_recorder() const { | |
1675 assert(DeoptC1, "need debug information"); | |
1676 return compilation()->dependency_recorder(); | |
1677 } | |
1678 | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1679 // How many arguments do we want to profile? |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1680 Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1681 int n = 0; |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1682 bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci())); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1683 start = has_receiver ? 1 : 0; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1684 if (profile_arguments()) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1685 ciProfileData* data = method()->method_data()->bci_to_data(bci()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1686 if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1687 n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments(); |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1688 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1689 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1690 // If we are inlining then we need to collect arguments to profile parameters for the target |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1691 if (profile_parameters() && target != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1692 if (target->method_data() != NULL && target->method_data()->parameters_type_data() != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1693 // The receiver is profiled on method entry so it's included in |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1694 // the number of parameters but here we're only interested in |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1695 // actual arguments. |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1696 n = MAX2(n, target->method_data()->parameters_type_data()->number_of_parameters() - start); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1697 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1698 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1699 if (n > 0) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1700 return new Values(n); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1701 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1702 return NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1703 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1704 |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1705 void GraphBuilder::check_args_for_profiling(Values* obj_args, int expected) { |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1706 #ifdef ASSERT |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1707 bool ignored_will_link; |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1708 ciSignature* declared_signature = NULL; |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1709 ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1710 assert(expected == obj_args->length() || real_target->is_method_handle_intrinsic(), "missed on arg?"); |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1711 #endif |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1712 } |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1713 |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1714 // Collect arguments that we want to profile in a list |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1715 Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1716 int start = 0; |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
1717 Values* obj_args = args_list_for_profiling(target, start, may_have_receiver); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1718 if (obj_args == NULL) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1719 return NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1720 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1721 int s = obj_args->size(); |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1722 // if called through method handle invoke, some arguments may have been popped |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1723 for (int i = start, j = 0; j < s && i < args->length(); i++) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1724 if (args->at(i)->type()->is_object_kind()) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1725 obj_args->push(args->at(i)); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1726 j++; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1727 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1728 } |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
1729 check_args_for_profiling(obj_args, s); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1730 return obj_args; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1731 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
1732 |
0 | 1733 |
1734 void GraphBuilder::invoke(Bytecodes::Code code) { | |
1735 bool will_link; | |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1736 ciSignature* declared_signature = NULL; |
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1737 ciMethod* target = stream()->get_method(will_link, &declared_signature); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1738 ciKlass* holder = stream()->get_declared_method_holder(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1739 const Bytecodes::Code bc_raw = stream()->cur_bc_raw(); |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1740 assert(declared_signature != NULL, "cannot be null"); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1741 |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1742 if (!C1PatchInvokeDynamic && Bytecodes::has_optional_appendix(bc_raw) && !will_link) { |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1743 BAILOUT("unlinked call site (C1PatchInvokeDynamic is off)"); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1744 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1745 |
0 | 1746 // we have to make sure the argument size (incl. the receiver) |
1747 // is correct for compilation (the call would fail later during | |
1748 // linkage anyway) - was bug (gri 7/28/99) | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1749 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1750 // Use raw to get rewritten bytecode. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1751 const bool is_invokestatic = bc_raw == Bytecodes::_invokestatic; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1752 const bool allow_static = |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1753 is_invokestatic || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1754 bc_raw == Bytecodes::_invokehandle || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1755 bc_raw == Bytecodes::_invokedynamic; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1756 if (target->is_loaded()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1757 if (( target->is_static() && !allow_static) || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1758 (!target->is_static() && is_invokestatic)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1759 BAILOUT("will cause link error"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1760 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1761 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1762 } |
0 | 1763 ciInstanceKlass* klass = target->holder(); |
1764 | |
1765 // check if CHA possible: if so, change the code to invoke_special | |
1766 ciInstanceKlass* calling_klass = method()->holder(); | |
1767 ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); | |
1768 ciInstanceKlass* actual_recv = callee_holder; | |
1769 | |
6843 | 1770 CompileLog* log = compilation()->log(); |
1771 if (log != NULL) | |
1772 log->elem("call method='%d' instr='%s'", | |
1773 log->identify(target), | |
1774 Bytecodes::name(code)); | |
1775 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1776 // Some methods are obviously bindable without any type checks so |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1777 // convert them directly to an invokespecial or invokestatic. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1778 if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1779 switch (bc_raw) { |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1780 case Bytecodes::_invokevirtual: |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1781 code = Bytecodes::_invokespecial; |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1782 break; |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1783 case Bytecodes::_invokehandle: |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1784 code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial; |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1785 break; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1786 } |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1787 } else { |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1788 if (bc_raw == Bytecodes::_invokehandle) { |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1789 assert(!will_link, "should come here only for unlinked call"); |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1790 code = Bytecodes::_invokespecial; |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1791 } |
0 | 1792 } |
1793 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1794 // Push appendix argument (MethodType, CallSite, etc.), if one. |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1795 bool patch_for_appendix = false; |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1796 int patching_appendix_arg = 0; |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1797 if (C1PatchInvokeDynamic && |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1798 (Bytecodes::has_optional_appendix(bc_raw) && (!will_link || PatchALot))) { |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1799 Value arg = append(new Constant(new ObjectConstant(compilation()->env()->unloaded_ciinstance()), copy_state_before())); |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1800 apush(arg); |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1801 patch_for_appendix = true; |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1802 patching_appendix_arg = (will_link && stream()->has_appendix()) ? 0 : 1; |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1803 } else if (stream()->has_appendix()) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1804 ciObject* appendix = stream()->get_appendix(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1805 Value arg = append(new Constant(new ObjectConstant(appendix))); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1806 apush(arg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1807 } |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1808 |
0 | 1809 // NEEDS_CLEANUP |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1810 // I've added the target->is_loaded() test below but I don't really understand |
0 | 1811 // how klass->is_loaded() can be true and yet target->is_loaded() is false. |
1812 // this happened while running the JCK invokevirtual tests under doit. TKR | |
1813 ciMethod* cha_monomorphic_target = NULL; | |
1814 ciMethod* exact_target = NULL; | |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1815 Value better_receiver = NULL; |
1295 | 1816 if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1817 !(// %%% FIXME: Are both of these relevant? |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1818 target->is_method_handle_intrinsic() || |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1819 target->is_compiled_lambda_form()) && |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1820 !patch_for_appendix) { |
0 | 1821 Value receiver = NULL; |
1822 ciInstanceKlass* receiver_klass = NULL; | |
1823 bool type_is_exact = false; | |
1824 // try to find a precise receiver type | |
1825 if (will_link && !target->is_static()) { | |
1826 int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); | |
1827 receiver = state()->stack_at(index); | |
1828 ciType* type = receiver->exact_type(); | |
1829 if (type != NULL && type->is_loaded() && | |
1830 type->is_instance_klass() && !type->as_instance_klass()->is_interface()) { | |
1831 receiver_klass = (ciInstanceKlass*) type; | |
1832 type_is_exact = true; | |
1833 } | |
1834 if (type == NULL) { | |
1835 type = receiver->declared_type(); | |
1836 if (type != NULL && type->is_loaded() && | |
1837 type->is_instance_klass() && !type->as_instance_klass()->is_interface()) { | |
1838 receiver_klass = (ciInstanceKlass*) type; | |
1839 if (receiver_klass->is_leaf_type() && !receiver_klass->is_final()) { | |
1840 // Insert a dependency on this type since | |
1841 // find_monomorphic_target may assume it's already done. | |
1842 dependency_recorder()->assert_leaf_type(receiver_klass); | |
1843 type_is_exact = true; | |
1844 } | |
1845 } | |
1846 } | |
1847 } | |
1848 if (receiver_klass != NULL && type_is_exact && | |
1849 receiver_klass->is_loaded() && code != Bytecodes::_invokespecial) { | |
1850 // If we have the exact receiver type we can bind directly to | |
1851 // the method to call. | |
1852 exact_target = target->resolve_invoke(calling_klass, receiver_klass); | |
1853 if (exact_target != NULL) { | |
1854 target = exact_target; | |
1855 code = Bytecodes::_invokespecial; | |
1856 } | |
1857 } | |
1858 if (receiver_klass != NULL && | |
1859 receiver_klass->is_subtype_of(actual_recv) && | |
1860 actual_recv->is_initialized()) { | |
1861 actual_recv = receiver_klass; | |
1862 } | |
1863 | |
1864 if ((code == Bytecodes::_invokevirtual && callee_holder->is_initialized()) || | |
1865 (code == Bytecodes::_invokeinterface && callee_holder->is_initialized() && !actual_recv->is_interface())) { | |
1866 // Use CHA on the receiver to select a more precise method. | |
1867 cha_monomorphic_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); | |
1868 } else if (code == Bytecodes::_invokeinterface && callee_holder->is_loaded() && receiver != NULL) { | |
1869 // if there is only one implementor of this interface then we | |
1870 // may be able bind this invoke directly to the implementing | |
1871 // klass but we need both a dependence on the single interface | |
1872 // and on the method we bind to. Additionally since all we know | |
1873 // about the receiver type is the it's supposed to implement the | |
1874 // interface we have to insert a check that it's the class we | |
1875 // expect. Interface types are not checked by the verifier so | |
1876 // they are roughly equivalent to Object. | |
1877 ciInstanceKlass* singleton = NULL; | |
1878 if (target->holder()->nof_implementors() == 1) { | |
5998
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
5926
diff
changeset
|
1879 singleton = target->holder()->implementor(); |
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
5926
diff
changeset
|
1880 assert(singleton != NULL && singleton != target->holder(), |
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
5926
diff
changeset
|
1881 "just checking"); |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1882 |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1883 assert(holder->is_interface(), "invokeinterface to non interface?"); |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1884 ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1885 // the number of implementors for decl_interface is less or |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1886 // equal to the number of implementors for target->holder() so |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1887 // if number of implementors of target->holder() == 1 then |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1888 // number of implementors for decl_interface is 0 or 1. If |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1889 // it's 0 then no class implements decl_interface and there's |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1890 // no point in inlining. |
13021
4d3575d37a07
8026735: Stream tests throw java.lang.IncompatibleClassChangeError
iveresov
parents:
12975
diff
changeset
|
1891 if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_default_methods()) { |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1892 singleton = NULL; |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1893 } |
0 | 1894 } |
1895 if (singleton) { | |
1896 cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); | |
1897 if (cha_monomorphic_target != NULL) { | |
1898 // If CHA is able to bind this invoke then update the class | |
1899 // to match that class, otherwise klass will refer to the | |
1900 // interface. | |
1901 klass = cha_monomorphic_target->holder(); | |
1902 actual_recv = target->holder(); | |
1903 | |
1904 // insert a check it's really the expected class. | |
1819 | 1905 CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); |
0 | 1906 c->set_incompatible_class_change_check(); |
1907 c->set_direct_compare(klass->is_final()); | |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1908 // pass the result of the checkcast so that the compiler has |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1909 // more accurate type info in the inlinee |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1910 better_receiver = append_split(c); |
0 | 1911 } |
1912 } | |
1913 } | |
1914 } | |
1915 | |
1916 if (cha_monomorphic_target != NULL) { | |
1917 if (cha_monomorphic_target->is_abstract()) { | |
1918 // Do not optimize for abstract methods | |
1919 cha_monomorphic_target = NULL; | |
1920 } | |
1921 } | |
1922 | |
1923 if (cha_monomorphic_target != NULL) { | |
1924 if (!(target->is_final_method())) { | |
1925 // If we inlined because CHA revealed only a single target method, | |
1926 // then we are dependent on that target method not getting overridden | |
1927 // by dynamic class loading. Be sure to test the "static" receiver | |
1928 // dest_method here, as opposed to the actual receiver, which may | |
1929 // falsely lead us to believe that the receiver is final or private. | |
1930 dependency_recorder()->assert_unique_concrete_method(actual_recv, cha_monomorphic_target); | |
1931 } | |
1932 code = Bytecodes::_invokespecial; | |
1933 } | |
6843 | 1934 |
0 | 1935 // check if we could do inlining |
1936 if (!PatchALot && Inline && klass->is_loaded() && | |
1937 (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) | |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1938 && target->is_loaded() |
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1939 && !patch_for_appendix) { |
0 | 1940 // callee is known => check if we have static binding |
1941 assert(target->is_loaded(), "callee must be known"); | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1942 if (code == Bytecodes::_invokestatic || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1943 code == Bytecodes::_invokespecial || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1944 code == Bytecodes::_invokevirtual && target->is_final_method() || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1945 code == Bytecodes::_invokedynamic) { |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1946 ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; |
6892
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
1947 // static binding => check if callee is ok |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
1948 bool success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver); |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
1949 |
0 | 1950 CHECK_BAILOUT(); |
1951 clear_inline_bailout(); | |
6892
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
1952 |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1953 if (success) { |
0 | 1954 // Register dependence if JVMTI has either breakpoint |
1955 // setting or hotswapping of methods capabilities since they may | |
1956 // cause deoptimization. | |
780
c96bf21b756f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
726
diff
changeset
|
1957 if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) { |
0 | 1958 dependency_recorder()->assert_evol_method(inline_target); |
1959 } | |
1960 return; | |
1961 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1962 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1963 print_inlining(target, "no static binding", /*success*/ false); |
0 | 1964 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1965 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1966 print_inlining(target, "not inlineable", /*success*/ false); |
0 | 1967 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1968 |
0 | 1969 // If we attempted an inline which did not succeed because of a |
1970 // bailout during construction of the callee graph, the entire | |
1971 // compilation has to be aborted. This is fairly rare and currently | |
1972 // seems to only occur for jasm-generated classes which contain | |
1973 // jsr/ret pairs which are not associated with finally clauses and | |
1974 // do not have exception handlers in the containing method, and are | |
1975 // therefore not caught early enough to abort the inlining without | |
1976 // corrupting the graph. (We currently bail out with a non-empty | |
1977 // stack at a ret in these situations.) | |
1978 CHECK_BAILOUT(); | |
1979 | |
1980 // inlining not successful => standard invoke | |
1295 | 1981 bool is_loaded = target->is_loaded(); |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1982 ValueType* result_type = as_ValueType(declared_signature->return_type()); |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1983 ValueStack* state_before = copy_state_exhandling(); |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1984 |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1985 // The bytecode (code) might change in this method so we are checking this very late. |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1986 const bool has_receiver = |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1987 code == Bytecodes::_invokespecial || |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1988 code == Bytecodes::_invokevirtual || |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1989 code == Bytecodes::_invokeinterface; |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
1990 Values* args = state()->pop_arguments(target->arg_size_no_receiver() + patching_appendix_arg); |
1295 | 1991 Value recv = has_receiver ? apop() : NULL; |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
1992 int vtable_index = Method::invalid_vtable_index; |
0 | 1993 |
1994 #ifdef SPARC | |
1995 // Currently only supported on Sparc. | |
1996 // The UseInlineCaches only controls dispatch to invokevirtuals for | |
1997 // loaded classes which we weren't able to statically bind. | |
1998 if (!UseInlineCaches && is_loaded && code == Bytecodes::_invokevirtual | |
1999 && !target->can_be_statically_bound()) { | |
2000 // Find a vtable index if one is available | |
18003
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2001 // For arrays, callee_holder is Object. Resolving the call with |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2002 // Object would allow an illegal call to finalize() on an |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2003 // array. We use holder instead: illegal calls to finalize() won't |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2004 // be compiled as vtable calls (IC call resolution will catch the |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2005 // illegal call) and the few legal calls on array types won't be |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2006 // either. |
dda2ae6f9557
8046542: [I.finalize() calls from methods compiled by C1 do not cause IllegalAccessError on Sparc
roland
parents:
17925
diff
changeset
|
2007 vtable_index = target->resolve_vtable_index(calling_klass, holder); |
0 | 2008 } |
2009 #endif | |
2010 | |
2011 if (recv != NULL && | |
2012 (code == Bytecodes::_invokespecial || | |
1783 | 2013 !is_loaded || target->is_final())) { |
0 | 2014 // invokespecial always needs a NULL check. invokevirtual where |
2015 // the target is final or where it's not known that whether the | |
2016 // target is final requires a NULL check. Otherwise normal | |
2017 // invokevirtual will perform the null check during the lookup | |
2018 // logic or the unverified entry point. Profiling of calls | |
2019 // requires that the null check is performed in all cases. | |
2020 null_check(recv); | |
2021 } | |
2022 | |
1783 | 2023 if (is_profiling()) { |
2024 if (recv != NULL && profile_calls()) { | |
2025 null_check(recv); | |
0 | 2026 } |
1783 | 2027 // Note that we'd collect profile data in this method if we wanted it. |
2028 compilation()->set_would_profile(true); | |
2029 | |
2030 if (profile_calls()) { | |
2031 assert(cha_monomorphic_target == NULL || exact_target == NULL, "both can not be set"); | |
2032 ciKlass* target_klass = NULL; | |
2033 if (cha_monomorphic_target != NULL) { | |
2034 target_klass = cha_monomorphic_target->holder(); | |
2035 } else if (exact_target != NULL) { | |
2036 target_klass = exact_target->holder(); | |
2037 } | |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
2038 profile_call(target, recv, target_klass, collect_args_for_profiling(args, NULL, false), false); |
1783 | 2039 } |
0 | 2040 } |
2041 | |
1295 | 2042 Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before); |
0 | 2043 // push result |
2044 append_split(result); | |
2045 | |
2046 if (result_type != voidType) { | |
2047 if (method()->is_strict()) { | |
2048 push(result_type, round_fp(result)); | |
2049 } else { | |
2050 push(result_type, result); | |
2051 } | |
2052 } | |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
2053 if (profile_return() && result_type->is_object_kind()) { |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
2054 profile_return_type(result, target); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
2055 } |
0 | 2056 } |
2057 | |
2058 | |
2059 void GraphBuilder::new_instance(int klass_index) { | |
1819 | 2060 ValueStack* state_before = copy_state_exhandling(); |
0 | 2061 bool will_link; |
2062 ciKlass* klass = stream()->get_klass(will_link); | |
2063 assert(klass->is_instance_klass(), "must be an instance klass"); | |
20344
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
18004
diff
changeset
|
2064 NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before, stream()->is_unresolved_klass()); |
0 | 2065 _memory->new_instance(new_instance); |
2066 apush(append_split(new_instance)); | |
2067 } | |
2068 | |
2069 | |
2070 void GraphBuilder::new_type_array() { | |
1819 | 2071 ValueStack* state_before = copy_state_exhandling(); |
2072 apush(append_split(new NewTypeArray(ipop(), (BasicType)stream()->get_index(), state_before))); | |
0 | 2073 } |
2074 | |
2075 | |
2076 void GraphBuilder::new_object_array() { | |
2077 bool will_link; | |
2078 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2079 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 2080 NewArray* n = new NewObjectArray(klass, ipop(), state_before); |
2081 apush(append_split(n)); | |
2082 } | |
2083 | |
2084 | |
2085 bool GraphBuilder::direct_compare(ciKlass* k) { | |
2086 if (k->is_loaded() && k->is_instance_klass() && !UseSlowPath) { | |
2087 ciInstanceKlass* ik = k->as_instance_klass(); | |
2088 if (ik->is_final()) { | |
2089 return true; | |
2090 } else { | |
2091 if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) { | |
2092 // test class is leaf class | |
2093 dependency_recorder()->assert_leaf_type(ik); | |
2094 return true; | |
2095 } | |
2096 } | |
2097 } | |
2098 return false; | |
2099 } | |
2100 | |
2101 | |
2102 void GraphBuilder::check_cast(int klass_index) { | |
2103 bool will_link; | |
2104 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2105 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_for_exception(); |
0 | 2106 CheckCast* c = new CheckCast(klass, apop(), state_before); |
2107 apush(append_split(c)); | |
2108 c->set_direct_compare(direct_compare(klass)); | |
1783 | 2109 |
2110 if (is_profiling()) { | |
2111 // Note that we'd collect profile data in this method if we wanted it. | |
2112 compilation()->set_would_profile(true); | |
2113 | |
2114 if (profile_checkcasts()) { | |
2115 c->set_profiled_method(method()); | |
2116 c->set_profiled_bci(bci()); | |
2117 c->set_should_profile(true); | |
2118 } | |
0 | 2119 } |
2120 } | |
2121 | |
2122 | |
2123 void GraphBuilder::instance_of(int klass_index) { | |
2124 bool will_link; | |
2125 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2126 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 2127 InstanceOf* i = new InstanceOf(klass, apop(), state_before); |
2128 ipush(append_split(i)); | |
2129 i->set_direct_compare(direct_compare(klass)); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2130 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2131 if (is_profiling()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2132 // Note that we'd collect profile data in this method if we wanted it. |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2133 compilation()->set_would_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2134 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2135 if (profile_checkcasts()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2136 i->set_profiled_method(method()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2137 i->set_profiled_bci(bci()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2138 i->set_should_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2139 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2140 } |
0 | 2141 } |
2142 | |
2143 | |
2144 void GraphBuilder::monitorenter(Value x, int bci) { | |
2145 // save state before locking in case of deoptimization after a NullPointerException | |
1819 | 2146 ValueStack* state_before = copy_state_for_exception_with_bci(bci); |
2147 append_with_bci(new MonitorEnter(x, state()->lock(x), state_before), bci); | |
0 | 2148 kill_all(); |
2149 } | |
2150 | |
2151 | |
2152 void GraphBuilder::monitorexit(Value x, int bci) { | |
2153 append_with_bci(new MonitorExit(x, state()->unlock()), bci); | |
2154 kill_all(); | |
2155 } | |
2156 | |
2157 | |
2158 void GraphBuilder::new_multi_array(int dimensions) { | |
2159 bool will_link; | |
2160 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2161 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 2162 |
2163 Values* dims = new Values(dimensions, NULL); | |
2164 // fill in all dimensions | |
2165 int i = dimensions; | |
2166 while (i-- > 0) dims->at_put(i, ipop()); | |
2167 // create array | |
2168 NewArray* n = new NewMultiArray(klass, dims, state_before); | |
2169 apush(append_split(n)); | |
2170 } | |
2171 | |
2172 | |
2173 void GraphBuilder::throw_op(int bci) { | |
2174 // We require that the debug info for a Throw be the "state before" | |
2175 // the Throw (i.e., exception oop is still on TOS) | |
1819 | 2176 ValueStack* state_before = copy_state_before_with_bci(bci); |
0 | 2177 Throw* t = new Throw(apop(), state_before); |
1819 | 2178 // operand stack not needed after a throw |
2179 state()->truncate_stack(0); | |
0 | 2180 append_with_bci(t, bci); |
2181 } | |
2182 | |
2183 | |
2184 Value GraphBuilder::round_fp(Value fp_value) { | |
2185 // no rounding needed if SSE2 is used | |
2186 if (RoundFPResults && UseSSE < 2) { | |
2187 // Must currently insert rounding node for doubleword values that | |
2188 // are results of expressions (i.e., not loads from memory or | |
2189 // constants) | |
2190 if (fp_value->type()->tag() == doubleTag && | |
2191 fp_value->as_Constant() == NULL && | |
2192 fp_value->as_Local() == NULL && // method parameters need no rounding | |
2193 fp_value->as_RoundFP() == NULL) { | |
2194 return append(new RoundFP(fp_value)); | |
2195 } | |
2196 } | |
2197 return fp_value; | |
2198 } | |
2199 | |
2200 | |
2201 Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) { | |
1783 | 2202 Canonicalizer canon(compilation(), instr, bci); |
0 | 2203 Instruction* i1 = canon.canonical(); |
1819 | 2204 if (i1->is_linked() || !i1->can_be_linked()) { |
0 | 2205 // Canonicalizer returned an instruction which was already |
2206 // appended so simply return it. | |
2207 return i1; | |
1819 | 2208 } |
2209 | |
2210 if (UseLocalValueNumbering) { | |
0 | 2211 // Lookup the instruction in the ValueMap and add it to the map if |
2212 // it's not found. | |
2213 Instruction* i2 = vmap()->find_insert(i1); | |
2214 if (i2 != i1) { | |
2215 // found an entry in the value map, so just return it. | |
1819 | 2216 assert(i2->is_linked(), "should already be linked"); |
0 | 2217 return i2; |
2218 } | |
459 | 2219 ValueNumberingEffects vne(vmap()); |
2220 i1->visit(&vne); | |
0 | 2221 } |
2222 | |
1819 | 2223 // i1 was not eliminated => append it |
2224 assert(i1->next() == NULL, "shouldn't already be linked"); | |
2225 _last = _last->set_next(i1, canon.bci()); | |
2226 | |
2227 if (++_instruction_count >= InstructionCountCutoff && !bailed_out()) { | |
2228 // set the bailout state but complete normal processing. We | |
2229 // might do a little more work before noticing the bailout so we | |
2230 // want processing to continue normally until it's noticed. | |
2231 bailout("Method and/or inlining is too large"); | |
2232 } | |
0 | 2233 |
2234 #ifndef PRODUCT | |
1819 | 2235 if (PrintIRDuringConstruction) { |
2236 InstructionPrinter ip; | |
2237 ip.print_line(i1); | |
2238 if (Verbose) { | |
2239 state()->print(); | |
2240 } | |
2241 } | |
2242 #endif | |
2243 | |
2244 // save state after modification of operand stack for StateSplit instructions | |
2245 StateSplit* s = i1->as_StateSplit(); | |
2246 if (s != NULL) { | |
2247 if (EliminateFieldAccess) { | |
2248 Intrinsic* intrinsic = s->as_Intrinsic(); | |
2249 if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) { | |
2250 _memory->kill(); | |
0 | 2251 } |
2252 } | |
1819 | 2253 s->set_state(state()->copy(ValueStack::StateAfter, canon.bci())); |
2254 } | |
2255 | |
2256 // set up exception handlers for this instruction if necessary | |
2257 if (i1->can_trap()) { | |
2258 i1->set_exception_handlers(handle_exception(i1)); | |
2259 assert(i1->exception_state() != NULL || !i1->needs_exception_state() || bailed_out(), "handle_exception must set exception state"); | |
0 | 2260 } |
2261 return i1; | |
2262 } | |
2263 | |
2264 | |
2265 Instruction* GraphBuilder::append(Instruction* instr) { | |
2266 assert(instr->as_StateSplit() == NULL || instr->as_BlockEnd() != NULL, "wrong append used"); | |
2267 return append_with_bci(instr, bci()); | |
2268 } | |
2269 | |
2270 | |
2271 Instruction* GraphBuilder::append_split(StateSplit* instr) { | |
2272 return append_with_bci(instr, bci()); | |
2273 } | |
2274 | |
2275 | |
2276 void GraphBuilder::null_check(Value value) { | |
2277 if (value->as_NewArray() != NULL || value->as_NewInstance() != NULL) { | |
2278 return; | |
2279 } else { | |
2280 Constant* con = value->as_Constant(); | |
2281 if (con) { | |
2282 ObjectType* c = con->type()->as_ObjectType(); | |
2283 if (c && c->is_loaded()) { | |
2284 ObjectConstant* oc = c->as_ObjectConstant(); | |
2285 if (!oc || !oc->value()->is_null_object()) { | |
2286 return; | |
2287 } | |
2288 } | |
2289 } | |
2290 } | |
1819 | 2291 append(new NullCheck(value, copy_state_for_exception())); |
0 | 2292 } |
2293 | |
2294 | |
2295 | |
1819 | 2296 XHandlers* GraphBuilder::handle_exception(Instruction* instruction) { |
2297 if (!has_handler() && (!instruction->needs_exception_state() || instruction->exception_state() != NULL)) { | |
2298 assert(instruction->exception_state() == NULL | |
2299 || instruction->exception_state()->kind() == ValueStack::EmptyExceptionState | |
2300 || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->jvmti_can_access_local_variables()), | |
2301 "exception_state should be of exception kind"); | |
0 | 2302 return new XHandlers(); |
2303 } | |
2304 | |
2305 XHandlers* exception_handlers = new XHandlers(); | |
2306 ScopeData* cur_scope_data = scope_data(); | |
1819 | 2307 ValueStack* cur_state = instruction->state_before(); |
2308 ValueStack* prev_state = NULL; | |
0 | 2309 int scope_count = 0; |
2310 | |
1819 | 2311 assert(cur_state != NULL, "state_before must be set"); |
0 | 2312 do { |
1819 | 2313 int cur_bci = cur_state->bci(); |
2314 assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match"); | |
0 | 2315 assert(cur_bci == SynchronizationEntryBCI || cur_bci == cur_scope_data->stream()->cur_bci(), "invalid bci"); |
2316 | |
2317 // join with all potential exception handlers | |
2318 XHandlers* list = cur_scope_data->xhandlers(); | |
2319 const int n = list->length(); | |
2320 for (int i = 0; i < n; i++) { | |
2321 XHandler* h = list->handler_at(i); | |
2322 if (h->covers(cur_bci)) { | |
2323 // h is a potential exception handler => join it | |
2324 compilation()->set_has_exception_handlers(true); | |
2325 | |
2326 BlockBegin* entry = h->entry_block(); | |
2327 if (entry == block()) { | |
2328 // It's acceptable for an exception handler to cover itself | |
2329 // but we don't handle that in the parser currently. It's | |
2330 // very rare so we bailout instead of trying to handle it. | |
2331 BAILOUT_("exception handler covers itself", exception_handlers); | |
2332 } | |
2333 assert(entry->bci() == h->handler_bci(), "must match"); | |
2334 assert(entry->bci() == -1 || entry == cur_scope_data->block_at(entry->bci()), "blocks must correspond"); | |
2335 | |
2336 // previously this was a BAILOUT, but this is not necessary | |
2337 // now because asynchronous exceptions are not handled this way. | |
1819 | 2338 assert(entry->state() == NULL || cur_state->total_locks_size() == entry->state()->total_locks_size(), "locks do not match"); |
0 | 2339 |
2340 // xhandler start with an empty expression stack | |
1819 | 2341 if (cur_state->stack_size() != 0) { |
2342 cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci()); | |
2343 } | |
2344 if (instruction->exception_state() == NULL) { | |
2345 instruction->set_exception_state(cur_state); | |
2346 } | |
0 | 2347 |
2348 // Note: Usually this join must work. However, very | |
2349 // complicated jsr-ret structures where we don't ret from | |
2350 // the subroutine can cause the objects on the monitor | |
2351 // stacks to not match because blocks can be parsed twice. | |
2352 // The only test case we've seen so far which exhibits this | |
2353 // problem is caught by the infinite recursion test in | |
2354 // GraphBuilder::jsr() if the join doesn't work. | |
1819 | 2355 if (!entry->try_merge(cur_state)) { |
0 | 2356 BAILOUT_("error while joining with exception handler, prob. due to complicated jsr/rets", exception_handlers); |
2357 } | |
2358 | |
2359 // add current state for correct handling of phi functions at begin of xhandler | |
1819 | 2360 int phi_operand = entry->add_exception_state(cur_state); |
0 | 2361 |
2362 // add entry to the list of xhandlers of this block | |
2363 _block->add_exception_handler(entry); | |
2364 | |
2365 // add back-edge from xhandler entry to this block | |
2366 if (!entry->is_predecessor(_block)) { | |
2367 entry->add_predecessor(_block); | |
2368 } | |
2369 | |
2370 // clone XHandler because phi_operand and scope_count can not be shared | |
2371 XHandler* new_xhandler = new XHandler(h); | |
2372 new_xhandler->set_phi_operand(phi_operand); | |
2373 new_xhandler->set_scope_count(scope_count); | |
2374 exception_handlers->append(new_xhandler); | |
2375 | |
2376 // fill in exception handler subgraph lazily | |
2377 assert(!entry->is_set(BlockBegin::was_visited_flag), "entry must not be visited yet"); | |
2378 cur_scope_data->add_to_work_list(entry); | |
2379 | |
2380 // stop when reaching catchall | |
2381 if (h->catch_type() == 0) { | |
2382 return exception_handlers; | |
2383 } | |
2384 } | |
2385 } | |
2386 | |
1819 | 2387 if (exception_handlers->length() == 0) { |
2388 // This scope and all callees do not handle exceptions, so the local | |
2389 // variables of this scope are not needed. However, the scope itself is | |
2390 // required for a correct exception stack trace -> clear out the locals. | |
2391 if (_compilation->env()->jvmti_can_access_local_variables()) { | |
2392 cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci()); | |
2393 } else { | |
2394 cur_state = cur_state->copy(ValueStack::EmptyExceptionState, cur_state->bci()); | |
2395 } | |
2396 if (prev_state != NULL) { | |
2397 prev_state->set_caller_state(cur_state); | |
2398 } | |
2399 if (instruction->exception_state() == NULL) { | |
2400 instruction->set_exception_state(cur_state); | |
2401 } | |
2402 } | |
2403 | |
0 | 2404 // Set up iteration for next time. |
2405 // If parsing a jsr, do not grab exception handlers from the | |
2406 // parent scopes for this method (already got them, and they | |
2407 // needed to be cloned) | |
1819 | 2408 |
2409 while (cur_scope_data->parsing_jsr()) { | |
2410 cur_scope_data = cur_scope_data->parent(); | |
0 | 2411 } |
1819 | 2412 |
2413 assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match"); | |
2414 assert(cur_state->locks_size() == 0 || cur_state->locks_size() == 1, "unlocking must be done in a catchall exception handler"); | |
2415 | |
2416 prev_state = cur_state; | |
2417 cur_state = cur_state->caller_state(); | |
2418 cur_scope_data = cur_scope_data->parent(); | |
2419 scope_count++; | |
0 | 2420 } while (cur_scope_data != NULL); |
2421 | |
2422 return exception_handlers; | |
2423 } | |
2424 | |
2425 | |
2426 // Helper class for simplifying Phis. | |
2427 class PhiSimplifier : public BlockClosure { | |
2428 private: | |
2429 bool _has_substitutions; | |
2430 Value simplify(Value v); | |
2431 | |
2432 public: | |
2433 PhiSimplifier(BlockBegin* start) : _has_substitutions(false) { | |
2434 start->iterate_preorder(this); | |
2435 if (_has_substitutions) { | |
2436 SubstitutionResolver sr(start); | |
2437 } | |
2438 } | |
2439 void block_do(BlockBegin* b); | |
2440 bool has_substitutions() const { return _has_substitutions; } | |
2441 }; | |
2442 | |
2443 | |
2444 Value PhiSimplifier::simplify(Value v) { | |
2445 Phi* phi = v->as_Phi(); | |
2446 | |
2447 if (phi == NULL) { | |
2448 // no phi function | |
2449 return v; | |
2450 } else if (v->has_subst()) { | |
2451 // already substituted; subst can be phi itself -> simplify | |
2452 return simplify(v->subst()); | |
2453 } else if (phi->is_set(Phi::cannot_simplify)) { | |
2454 // already tried to simplify phi before | |
2455 return phi; | |
2456 } else if (phi->is_set(Phi::visited)) { | |
2457 // break cycles in phi functions | |
2458 return phi; | |
2459 } else if (phi->type()->is_illegal()) { | |
2460 // illegal phi functions are ignored anyway | |
2461 return phi; | |
2462 | |
2463 } else { | |
2464 // mark phi function as processed to break cycles in phi functions | |
2465 phi->set(Phi::visited); | |
2466 | |
2467 // simplify x = [y, x] and x = [y, y] to y | |
2468 Value subst = NULL; | |
2469 int opd_count = phi->operand_count(); | |
2470 for (int i = 0; i < opd_count; i++) { | |
2471 Value opd = phi->operand_at(i); | |
2472 assert(opd != NULL, "Operand must exist!"); | |
2473 | |
2474 if (opd->type()->is_illegal()) { | |
2475 // if one operand is illegal, the entire phi function is illegal | |
2476 phi->make_illegal(); | |
2477 phi->clear(Phi::visited); | |
2478 return phi; | |
2479 } | |
2480 | |
2481 Value new_opd = simplify(opd); | |
2482 assert(new_opd != NULL, "Simplified operand must exist!"); | |
2483 | |
2484 if (new_opd != phi && new_opd != subst) { | |
2485 if (subst == NULL) { | |
2486 subst = new_opd; | |
2487 } else { | |
2488 // no simplification possible | |
2489 phi->set(Phi::cannot_simplify); | |
2490 phi->clear(Phi::visited); | |
2491 return phi; | |
2492 } | |
2493 } | |
2494 } | |
2495 | |
2496 // sucessfully simplified phi function | |
2497 assert(subst != NULL, "illegal phi function"); | |
2498 _has_substitutions = true; | |
2499 phi->clear(Phi::visited); | |
2500 phi->set_subst(subst); | |
2501 | |
2502 #ifndef PRODUCT | |
2503 if (PrintPhiFunctions) { | |
2504 tty->print_cr("simplified phi function %c%d to %c%d (Block B%d)", phi->type()->tchar(), phi->id(), subst->type()->tchar(), subst->id(), phi->block()->block_id()); | |
2505 } | |
2506 #endif | |
2507 | |
2508 return subst; | |
2509 } | |
2510 } | |
2511 | |
2512 | |
2513 void PhiSimplifier::block_do(BlockBegin* b) { | |
2514 for_each_phi_fun(b, phi, | |
2515 simplify(phi); | |
2516 ); | |
2517 | |
2518 #ifdef ASSERT | |
2519 for_each_phi_fun(b, phi, | |
2520 assert(phi->operand_count() != 1 || phi->subst() != phi, "missed trivial simplification"); | |
2521 ); | |
2522 | |
2523 ValueStack* state = b->state()->caller_state(); | |
1819 | 2524 for_each_state_value(state, value, |
2525 Phi* phi = value->as_Phi(); | |
2526 assert(phi == NULL || phi->block() != b, "must not have phi function to simplify in caller state"); | |
2527 ); | |
0 | 2528 #endif |
2529 } | |
2530 | |
2531 // This method is called after all blocks are filled with HIR instructions | |
2532 // It eliminates all Phi functions of the form x = [y, y] and x = [y, x] | |
2533 void GraphBuilder::eliminate_redundant_phis(BlockBegin* start) { | |
2534 PhiSimplifier simplifier(start); | |
2535 } | |
2536 | |
2537 | |
2538 void GraphBuilder::connect_to_end(BlockBegin* beg) { | |
2539 // setup iteration | |
2540 kill_all(); | |
2541 _block = beg; | |
1819 | 2542 _state = beg->state()->copy_for_parsing(); |
0 | 2543 _last = beg; |
2544 iterate_bytecodes_for_block(beg->bci()); | |
2545 } | |
2546 | |
2547 | |
2548 BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { | |
2549 #ifndef PRODUCT | |
2550 if (PrintIRDuringConstruction) { | |
2551 tty->cr(); | |
2552 InstructionPrinter ip; | |
2553 ip.print_instr(_block); tty->cr(); | |
2554 ip.print_stack(_block->state()); tty->cr(); | |
2555 ip.print_inline_level(_block); | |
2556 ip.print_head(); | |
2557 tty->print_cr("locals size: %d stack size: %d", state()->locals_size(), state()->stack_size()); | |
2558 } | |
2559 #endif | |
2560 _skip_block = false; | |
2561 assert(state() != NULL, "ValueStack missing!"); | |
6843 | 2562 CompileLog* log = compilation()->log(); |
0 | 2563 ciBytecodeStream s(method()); |
2564 s.reset_to_bci(bci); | |
2565 int prev_bci = bci; | |
2566 scope_data()->set_stream(&s); | |
2567 // iterate | |
2568 Bytecodes::Code code = Bytecodes::_illegal; | |
2569 bool push_exception = false; | |
2570 | |
2571 if (block()->is_set(BlockBegin::exception_entry_flag) && block()->next() == NULL) { | |
2572 // first thing in the exception entry block should be the exception object. | |
2573 push_exception = true; | |
2574 } | |
2575 | |
2576 while (!bailed_out() && last()->as_BlockEnd() == NULL && | |
2577 (code = stream()->next()) != ciBytecodeStream::EOBC() && | |
2578 (block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) { | |
1819 | 2579 assert(state()->kind() == ValueStack::Parsing, "invalid state kind"); |
0 | 2580 |
6843 | 2581 if (log != NULL) |
2582 log->set_context("bc code='%d' bci='%d'", (int)code, s.cur_bci()); | |
2583 | |
0 | 2584 // Check for active jsr during OSR compilation |
2585 if (compilation()->is_osr_compile() | |
2586 && scope()->is_top_scope() | |
2587 && parsing_jsr() | |
2588 && s.cur_bci() == compilation()->osr_bci()) { | |
2589 bailout("OSR not supported while a jsr is active"); | |
2590 } | |
2591 | |
2592 if (push_exception) { | |
2593 apush(append(new ExceptionObject())); | |
2594 push_exception = false; | |
2595 } | |
2596 | |
2597 // handle bytecode | |
2598 switch (code) { | |
2599 case Bytecodes::_nop : /* nothing to do */ break; | |
2600 case Bytecodes::_aconst_null : apush(append(new Constant(objectNull ))); break; | |
2601 case Bytecodes::_iconst_m1 : ipush(append(new Constant(new IntConstant (-1)))); break; | |
2602 case Bytecodes::_iconst_0 : ipush(append(new Constant(intZero ))); break; | |
2603 case Bytecodes::_iconst_1 : ipush(append(new Constant(intOne ))); break; | |
2604 case Bytecodes::_iconst_2 : ipush(append(new Constant(new IntConstant ( 2)))); break; | |
2605 case Bytecodes::_iconst_3 : ipush(append(new Constant(new IntConstant ( 3)))); break; | |
2606 case Bytecodes::_iconst_4 : ipush(append(new Constant(new IntConstant ( 4)))); break; | |
2607 case Bytecodes::_iconst_5 : ipush(append(new Constant(new IntConstant ( 5)))); break; | |
2608 case Bytecodes::_lconst_0 : lpush(append(new Constant(new LongConstant ( 0)))); break; | |
2609 case Bytecodes::_lconst_1 : lpush(append(new Constant(new LongConstant ( 1)))); break; | |
2610 case Bytecodes::_fconst_0 : fpush(append(new Constant(new FloatConstant ( 0)))); break; | |
2611 case Bytecodes::_fconst_1 : fpush(append(new Constant(new FloatConstant ( 1)))); break; | |
2612 case Bytecodes::_fconst_2 : fpush(append(new Constant(new FloatConstant ( 2)))); break; | |
2613 case Bytecodes::_dconst_0 : dpush(append(new Constant(new DoubleConstant( 0)))); break; | |
2614 case Bytecodes::_dconst_1 : dpush(append(new Constant(new DoubleConstant( 1)))); break; | |
2615 case Bytecodes::_bipush : ipush(append(new Constant(new IntConstant(((signed char*)s.cur_bcp())[1])))); break; | |
2616 case Bytecodes::_sipush : ipush(append(new Constant(new IntConstant((short)Bytes::get_Java_u2(s.cur_bcp()+1))))); break; | |
2617 case Bytecodes::_ldc : // fall through | |
2618 case Bytecodes::_ldc_w : // fall through | |
2619 case Bytecodes::_ldc2_w : load_constant(); break; | |
2620 case Bytecodes::_iload : load_local(intType , s.get_index()); break; | |
2621 case Bytecodes::_lload : load_local(longType , s.get_index()); break; | |
2622 case Bytecodes::_fload : load_local(floatType , s.get_index()); break; | |
2623 case Bytecodes::_dload : load_local(doubleType , s.get_index()); break; | |
2624 case Bytecodes::_aload : load_local(instanceType, s.get_index()); break; | |
2625 case Bytecodes::_iload_0 : load_local(intType , 0); break; | |
2626 case Bytecodes::_iload_1 : load_local(intType , 1); break; | |
2627 case Bytecodes::_iload_2 : load_local(intType , 2); break; | |
2628 case Bytecodes::_iload_3 : load_local(intType , 3); break; | |
2629 case Bytecodes::_lload_0 : load_local(longType , 0); break; | |
2630 case Bytecodes::_lload_1 : load_local(longType , 1); break; | |
2631 case Bytecodes::_lload_2 : load_local(longType , 2); break; | |
2632 case Bytecodes::_lload_3 : load_local(longType , 3); break; | |
2633 case Bytecodes::_fload_0 : load_local(floatType , 0); break; | |
2634 case Bytecodes::_fload_1 : load_local(floatType , 1); break; | |
2635 case Bytecodes::_fload_2 : load_local(floatType , 2); break; | |
2636 case Bytecodes::_fload_3 : load_local(floatType , 3); break; | |
2637 case Bytecodes::_dload_0 : load_local(doubleType, 0); break; | |
2638 case Bytecodes::_dload_1 : load_local(doubleType, 1); break; | |
2639 case Bytecodes::_dload_2 : load_local(doubleType, 2); break; | |
2640 case Bytecodes::_dload_3 : load_local(doubleType, 3); break; | |
2641 case Bytecodes::_aload_0 : load_local(objectType, 0); break; | |
2642 case Bytecodes::_aload_1 : load_local(objectType, 1); break; | |
2643 case Bytecodes::_aload_2 : load_local(objectType, 2); break; | |
2644 case Bytecodes::_aload_3 : load_local(objectType, 3); break; | |
2645 case Bytecodes::_iaload : load_indexed(T_INT ); break; | |
2646 case Bytecodes::_laload : load_indexed(T_LONG ); break; | |
2647 case Bytecodes::_faload : load_indexed(T_FLOAT ); break; | |
2648 case Bytecodes::_daload : load_indexed(T_DOUBLE); break; | |
2649 case Bytecodes::_aaload : load_indexed(T_OBJECT); break; | |
2650 case Bytecodes::_baload : load_indexed(T_BYTE ); break; | |
2651 case Bytecodes::_caload : load_indexed(T_CHAR ); break; | |
2652 case Bytecodes::_saload : load_indexed(T_SHORT ); break; | |
2653 case Bytecodes::_istore : store_local(intType , s.get_index()); break; | |
2654 case Bytecodes::_lstore : store_local(longType , s.get_index()); break; | |
2655 case Bytecodes::_fstore : store_local(floatType , s.get_index()); break; | |
2656 case Bytecodes::_dstore : store_local(doubleType, s.get_index()); break; | |
2657 case Bytecodes::_astore : store_local(objectType, s.get_index()); break; | |
2658 case Bytecodes::_istore_0 : store_local(intType , 0); break; | |
2659 case Bytecodes::_istore_1 : store_local(intType , 1); break; | |
2660 case Bytecodes::_istore_2 : store_local(intType , 2); break; | |
2661 case Bytecodes::_istore_3 : store_local(intType , 3); break; | |
2662 case Bytecodes::_lstore_0 : store_local(longType , 0); break; | |
2663 case Bytecodes::_lstore_1 : store_local(longType , 1); break; | |
2664 case Bytecodes::_lstore_2 : store_local(longType , 2); break; | |
2665 case Bytecodes::_lstore_3 : store_local(longType , 3); break; | |
2666 case Bytecodes::_fstore_0 : store_local(floatType , 0); break; | |
2667 case Bytecodes::_fstore_1 : store_local(floatType , 1); break; | |
2668 case Bytecodes::_fstore_2 : store_local(floatType , 2); break; | |
2669 case Bytecodes::_fstore_3 : store_local(floatType , 3); break; | |
2670 case Bytecodes::_dstore_0 : store_local(doubleType, 0); break; | |
2671 case Bytecodes::_dstore_1 : store_local(doubleType, 1); break; | |
2672 case Bytecodes::_dstore_2 : store_local(doubleType, 2); break; | |
2673 case Bytecodes::_dstore_3 : store_local(doubleType, 3); break; | |
2674 case Bytecodes::_astore_0 : store_local(objectType, 0); break; | |
2675 case Bytecodes::_astore_1 : store_local(objectType, 1); break; | |
2676 case Bytecodes::_astore_2 : store_local(objectType, 2); break; | |
2677 case Bytecodes::_astore_3 : store_local(objectType, 3); break; | |
2678 case Bytecodes::_iastore : store_indexed(T_INT ); break; | |
2679 case Bytecodes::_lastore : store_indexed(T_LONG ); break; | |
2680 case Bytecodes::_fastore : store_indexed(T_FLOAT ); break; | |
2681 case Bytecodes::_dastore : store_indexed(T_DOUBLE); break; | |
2682 case Bytecodes::_aastore : store_indexed(T_OBJECT); break; | |
2683 case Bytecodes::_bastore : store_indexed(T_BYTE ); break; | |
2684 case Bytecodes::_castore : store_indexed(T_CHAR ); break; | |
2685 case Bytecodes::_sastore : store_indexed(T_SHORT ); break; | |
2686 case Bytecodes::_pop : // fall through | |
2687 case Bytecodes::_pop2 : // fall through | |
2688 case Bytecodes::_dup : // fall through | |
2689 case Bytecodes::_dup_x1 : // fall through | |
2690 case Bytecodes::_dup_x2 : // fall through | |
2691 case Bytecodes::_dup2 : // fall through | |
2692 case Bytecodes::_dup2_x1 : // fall through | |
2693 case Bytecodes::_dup2_x2 : // fall through | |
2694 case Bytecodes::_swap : stack_op(code); break; | |
2695 case Bytecodes::_iadd : arithmetic_op(intType , code); break; | |
2696 case Bytecodes::_ladd : arithmetic_op(longType , code); break; | |
2697 case Bytecodes::_fadd : arithmetic_op(floatType , code); break; | |
2698 case Bytecodes::_dadd : arithmetic_op(doubleType, code); break; | |
2699 case Bytecodes::_isub : arithmetic_op(intType , code); break; | |
2700 case Bytecodes::_lsub : arithmetic_op(longType , code); break; | |
2701 case Bytecodes::_fsub : arithmetic_op(floatType , code); break; | |
2702 case Bytecodes::_dsub : arithmetic_op(doubleType, code); break; | |
2703 case Bytecodes::_imul : arithmetic_op(intType , code); break; | |
2704 case Bytecodes::_lmul : arithmetic_op(longType , code); break; | |
2705 case Bytecodes::_fmul : arithmetic_op(floatType , code); break; | |
2706 case Bytecodes::_dmul : arithmetic_op(doubleType, code); break; | |
1819 | 2707 case Bytecodes::_idiv : arithmetic_op(intType , code, copy_state_for_exception()); break; |
2708 case Bytecodes::_ldiv : arithmetic_op(longType , code, copy_state_for_exception()); break; | |
0 | 2709 case Bytecodes::_fdiv : arithmetic_op(floatType , code); break; |
2710 case Bytecodes::_ddiv : arithmetic_op(doubleType, code); break; | |
1819 | 2711 case Bytecodes::_irem : arithmetic_op(intType , code, copy_state_for_exception()); break; |
2712 case Bytecodes::_lrem : arithmetic_op(longType , code, copy_state_for_exception()); break; | |
0 | 2713 case Bytecodes::_frem : arithmetic_op(floatType , code); break; |
2714 case Bytecodes::_drem : arithmetic_op(doubleType, code); break; | |
2715 case Bytecodes::_ineg : negate_op(intType ); break; | |
2716 case Bytecodes::_lneg : negate_op(longType ); break; | |
2717 case Bytecodes::_fneg : negate_op(floatType ); break; | |
2718 case Bytecodes::_dneg : negate_op(doubleType); break; | |
2719 case Bytecodes::_ishl : shift_op(intType , code); break; | |
2720 case Bytecodes::_lshl : shift_op(longType, code); break; | |
2721 case Bytecodes::_ishr : shift_op(intType , code); break; | |
2722 case Bytecodes::_lshr : shift_op(longType, code); break; | |
2723 case Bytecodes::_iushr : shift_op(intType , code); break; | |
2724 case Bytecodes::_lushr : shift_op(longType, code); break; | |
2725 case Bytecodes::_iand : logic_op(intType , code); break; | |
2726 case Bytecodes::_land : logic_op(longType, code); break; | |
2727 case Bytecodes::_ior : logic_op(intType , code); break; | |
2728 case Bytecodes::_lor : logic_op(longType, code); break; | |
2729 case Bytecodes::_ixor : logic_op(intType , code); break; | |
2730 case Bytecodes::_lxor : logic_op(longType, code); break; | |
2731 case Bytecodes::_iinc : increment(); break; | |
2732 case Bytecodes::_i2l : convert(code, T_INT , T_LONG ); break; | |
2733 case Bytecodes::_i2f : convert(code, T_INT , T_FLOAT ); break; | |
2734 case Bytecodes::_i2d : convert(code, T_INT , T_DOUBLE); break; | |
2735 case Bytecodes::_l2i : convert(code, T_LONG , T_INT ); break; | |
2736 case Bytecodes::_l2f : convert(code, T_LONG , T_FLOAT ); break; | |
2737 case Bytecodes::_l2d : convert(code, T_LONG , T_DOUBLE); break; | |
2738 case Bytecodes::_f2i : convert(code, T_FLOAT , T_INT ); break; | |
2739 case Bytecodes::_f2l : convert(code, T_FLOAT , T_LONG ); break; | |
2740 case Bytecodes::_f2d : convert(code, T_FLOAT , T_DOUBLE); break; | |
2741 case Bytecodes::_d2i : convert(code, T_DOUBLE, T_INT ); break; | |
2742 case Bytecodes::_d2l : convert(code, T_DOUBLE, T_LONG ); break; | |
2743 case Bytecodes::_d2f : convert(code, T_DOUBLE, T_FLOAT ); break; | |
2744 case Bytecodes::_i2b : convert(code, T_INT , T_BYTE ); break; | |
2745 case Bytecodes::_i2c : convert(code, T_INT , T_CHAR ); break; | |
2746 case Bytecodes::_i2s : convert(code, T_INT , T_SHORT ); break; | |
2747 case Bytecodes::_lcmp : compare_op(longType , code); break; | |
2748 case Bytecodes::_fcmpl : compare_op(floatType , code); break; | |
2749 case Bytecodes::_fcmpg : compare_op(floatType , code); break; | |
2750 case Bytecodes::_dcmpl : compare_op(doubleType, code); break; | |
2751 case Bytecodes::_dcmpg : compare_op(doubleType, code); break; | |
2752 case Bytecodes::_ifeq : if_zero(intType , If::eql); break; | |
2753 case Bytecodes::_ifne : if_zero(intType , If::neq); break; | |
2754 case Bytecodes::_iflt : if_zero(intType , If::lss); break; | |
2755 case Bytecodes::_ifge : if_zero(intType , If::geq); break; | |
2756 case Bytecodes::_ifgt : if_zero(intType , If::gtr); break; | |
2757 case Bytecodes::_ifle : if_zero(intType , If::leq); break; | |
2758 case Bytecodes::_if_icmpeq : if_same(intType , If::eql); break; | |
2759 case Bytecodes::_if_icmpne : if_same(intType , If::neq); break; | |
2760 case Bytecodes::_if_icmplt : if_same(intType , If::lss); break; | |
2761 case Bytecodes::_if_icmpge : if_same(intType , If::geq); break; | |
2762 case Bytecodes::_if_icmpgt : if_same(intType , If::gtr); break; | |
2763 case Bytecodes::_if_icmple : if_same(intType , If::leq); break; | |
2764 case Bytecodes::_if_acmpeq : if_same(objectType, If::eql); break; | |
2765 case Bytecodes::_if_acmpne : if_same(objectType, If::neq); break; | |
2766 case Bytecodes::_goto : _goto(s.cur_bci(), s.get_dest()); break; | |
2767 case Bytecodes::_jsr : jsr(s.get_dest()); break; | |
2768 case Bytecodes::_ret : ret(s.get_index()); break; | |
2769 case Bytecodes::_tableswitch : table_switch(); break; | |
2770 case Bytecodes::_lookupswitch : lookup_switch(); break; | |
2771 case Bytecodes::_ireturn : method_return(ipop()); break; | |
2772 case Bytecodes::_lreturn : method_return(lpop()); break; | |
2773 case Bytecodes::_freturn : method_return(fpop()); break; | |
2774 case Bytecodes::_dreturn : method_return(dpop()); break; | |
2775 case Bytecodes::_areturn : method_return(apop()); break; | |
2776 case Bytecodes::_return : method_return(NULL ); break; | |
2777 case Bytecodes::_getstatic : // fall through | |
2778 case Bytecodes::_putstatic : // fall through | |
2779 case Bytecodes::_getfield : // fall through | |
2780 case Bytecodes::_putfield : access_field(code); break; | |
2781 case Bytecodes::_invokevirtual : // fall through | |
2782 case Bytecodes::_invokespecial : // fall through | |
2783 case Bytecodes::_invokestatic : // fall through | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
470
diff
changeset
|
2784 case Bytecodes::_invokedynamic : // fall through |
0 | 2785 case Bytecodes::_invokeinterface: invoke(code); break; |
1565 | 2786 case Bytecodes::_new : new_instance(s.get_index_u2()); break; |
0 | 2787 case Bytecodes::_newarray : new_type_array(); break; |
2788 case Bytecodes::_anewarray : new_object_array(); break; | |
1819 | 2789 case Bytecodes::_arraylength : { ValueStack* state_before = copy_state_for_exception(); ipush(append(new ArrayLength(apop(), state_before))); break; } |
0 | 2790 case Bytecodes::_athrow : throw_op(s.cur_bci()); break; |
1565 | 2791 case Bytecodes::_checkcast : check_cast(s.get_index_u2()); break; |
2792 case Bytecodes::_instanceof : instance_of(s.get_index_u2()); break; | |
0 | 2793 case Bytecodes::_monitorenter : monitorenter(apop(), s.cur_bci()); break; |
2794 case Bytecodes::_monitorexit : monitorexit (apop(), s.cur_bci()); break; | |
2795 case Bytecodes::_wide : ShouldNotReachHere(); break; | |
2796 case Bytecodes::_multianewarray : new_multi_array(s.cur_bcp()[3]); break; | |
2797 case Bytecodes::_ifnull : if_null(objectType, If::eql); break; | |
2798 case Bytecodes::_ifnonnull : if_null(objectType, If::neq); break; | |
2799 case Bytecodes::_goto_w : _goto(s.cur_bci(), s.get_far_dest()); break; | |
2800 case Bytecodes::_jsr_w : jsr(s.get_far_dest()); break; | |
2801 case Bytecodes::_breakpoint : BAILOUT_("concurrent setting of breakpoint", NULL); | |
2802 default : ShouldNotReachHere(); break; | |
2803 } | |
6843 | 2804 |
2805 if (log != NULL) | |
2806 log->clear_context(); // skip marker if nothing was printed | |
2807 | |
0 | 2808 // save current bci to setup Goto at the end |
2809 prev_bci = s.cur_bci(); | |
6843 | 2810 |
0 | 2811 } |
2812 CHECK_BAILOUT_(NULL); | |
2813 // stop processing of this block (see try_inline_full) | |
2814 if (_skip_block) { | |
2815 _skip_block = false; | |
2816 assert(_last && _last->as_BlockEnd(), ""); | |
2817 return _last->as_BlockEnd(); | |
2818 } | |
2819 // if there are any, check if last instruction is a BlockEnd instruction | |
2820 BlockEnd* end = last()->as_BlockEnd(); | |
2821 if (end == NULL) { | |
2822 // all blocks must end with a BlockEnd instruction => add a Goto | |
2823 end = new Goto(block_at(s.cur_bci()), false); | |
1819 | 2824 append(end); |
0 | 2825 } |
2826 assert(end == last()->as_BlockEnd(), "inconsistency"); | |
2827 | |
1819 | 2828 assert(end->state() != NULL, "state must already be present"); |
2829 assert(end->as_Return() == NULL || end->as_Throw() == NULL || end->state()->stack_size() == 0, "stack not needed for return and throw"); | |
0 | 2830 |
2831 // connect to begin & set state | |
2832 // NOTE that inlining may have changed the block we are parsing | |
2833 block()->set_end(end); | |
2834 // propagate state | |
2835 for (int i = end->number_of_sux() - 1; i >= 0; i--) { | |
2836 BlockBegin* sux = end->sux_at(i); | |
2837 assert(sux->is_predecessor(block()), "predecessor missing"); | |
2838 // be careful, bailout if bytecodes are strange | |
1819 | 2839 if (!sux->try_merge(end->state())) BAILOUT_("block join failed", NULL); |
0 | 2840 scope_data()->add_to_work_list(end->sux_at(i)); |
2841 } | |
2842 | |
2843 scope_data()->set_stream(NULL); | |
2844 | |
2845 // done | |
2846 return end; | |
2847 } | |
2848 | |
2849 | |
2850 void GraphBuilder::iterate_all_blocks(bool start_in_current_block_for_inlining) { | |
2851 do { | |
2852 if (start_in_current_block_for_inlining && !bailed_out()) { | |
2853 iterate_bytecodes_for_block(0); | |
2854 start_in_current_block_for_inlining = false; | |
2855 } else { | |
2856 BlockBegin* b; | |
2857 while ((b = scope_data()->remove_from_work_list()) != NULL) { | |
2858 if (!b->is_set(BlockBegin::was_visited_flag)) { | |
2859 if (b->is_set(BlockBegin::osr_entry_flag)) { | |
2860 // we're about to parse the osr entry block, so make sure | |
2861 // we setup the OSR edge leading into this block so that | |
2862 // Phis get setup correctly. | |
2863 setup_osr_entry_block(); | |
2864 // this is no longer the osr entry block, so clear it. | |
2865 b->clear(BlockBegin::osr_entry_flag); | |
2866 } | |
2867 b->set(BlockBegin::was_visited_flag); | |
2868 connect_to_end(b); | |
2869 } | |
2870 } | |
2871 } | |
2872 } while (!bailed_out() && !scope_data()->is_work_list_empty()); | |
2873 } | |
2874 | |
2875 | |
2876 bool GraphBuilder::_can_trap [Bytecodes::number_of_java_codes]; | |
2877 | |
2878 void GraphBuilder::initialize() { | |
2879 // the following bytecodes are assumed to potentially | |
2880 // throw exceptions in compiled code - note that e.g. | |
2881 // monitorexit & the return bytecodes do not throw | |
2882 // exceptions since monitor pairing proved that they | |
2883 // succeed (if monitor pairing succeeded) | |
2884 Bytecodes::Code can_trap_list[] = | |
2885 { Bytecodes::_ldc | |
2886 , Bytecodes::_ldc_w | |
2887 , Bytecodes::_ldc2_w | |
2888 , Bytecodes::_iaload | |
2889 , Bytecodes::_laload | |
2890 , Bytecodes::_faload | |
2891 , Bytecodes::_daload | |
2892 , Bytecodes::_aaload | |
2893 , Bytecodes::_baload | |
2894 , Bytecodes::_caload | |
2895 , Bytecodes::_saload | |
2896 , Bytecodes::_iastore | |
2897 , Bytecodes::_lastore | |
2898 , Bytecodes::_fastore | |
2899 , Bytecodes::_dastore | |
2900 , Bytecodes::_aastore | |
2901 , Bytecodes::_bastore | |
2902 , Bytecodes::_castore | |
2903 , Bytecodes::_sastore | |
2904 , Bytecodes::_idiv | |
2905 , Bytecodes::_ldiv | |
2906 , Bytecodes::_irem | |
2907 , Bytecodes::_lrem | |
2908 , Bytecodes::_getstatic | |
2909 , Bytecodes::_putstatic | |
2910 , Bytecodes::_getfield | |
2911 , Bytecodes::_putfield | |
2912 , Bytecodes::_invokevirtual | |
2913 , Bytecodes::_invokespecial | |
2914 , Bytecodes::_invokestatic | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
470
diff
changeset
|
2915 , Bytecodes::_invokedynamic |
0 | 2916 , Bytecodes::_invokeinterface |
2917 , Bytecodes::_new | |
2918 , Bytecodes::_newarray | |
2919 , Bytecodes::_anewarray | |
2920 , Bytecodes::_arraylength | |
2921 , Bytecodes::_athrow | |
2922 , Bytecodes::_checkcast | |
2923 , Bytecodes::_instanceof | |
2924 , Bytecodes::_monitorenter | |
2925 , Bytecodes::_multianewarray | |
2926 }; | |
2927 | |
2928 // inititialize trap tables | |
2929 for (int i = 0; i < Bytecodes::number_of_java_codes; i++) { | |
2930 _can_trap[i] = false; | |
2931 } | |
2932 // set standard trap info | |
2933 for (uint j = 0; j < ARRAY_SIZE(can_trap_list); j++) { | |
2934 _can_trap[can_trap_list[j]] = true; | |
2935 } | |
2936 } | |
2937 | |
2938 | |
2939 BlockBegin* GraphBuilder::header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state) { | |
2940 assert(entry->is_set(f), "entry/flag mismatch"); | |
2941 // create header block | |
2942 BlockBegin* h = new BlockBegin(entry->bci()); | |
2943 h->set_depth_first_number(0); | |
2944 | |
2945 Value l = h; | |
2946 BlockEnd* g = new Goto(entry, false); | |
2947 l->set_next(g, entry->bci()); | |
2948 h->set_end(g); | |
2949 h->set(f); | |
2950 // setup header block end state | |
1819 | 2951 ValueStack* s = state->copy(ValueStack::StateAfter, entry->bci()); // can use copy since stack is empty (=> no phis) |
0 | 2952 assert(s->stack_is_empty(), "must have empty stack at entry point"); |
2953 g->set_state(s); | |
2954 return h; | |
2955 } | |
2956 | |
2957 | |
2958 | |
2959 BlockBegin* GraphBuilder::setup_start_block(int osr_bci, BlockBegin* std_entry, BlockBegin* osr_entry, ValueStack* state) { | |
2960 BlockBegin* start = new BlockBegin(0); | |
2961 | |
2962 // This code eliminates the empty start block at the beginning of | |
2963 // each method. Previously, each method started with the | |
2964 // start-block created below, and this block was followed by the | |
2965 // header block that was always empty. This header block is only | |
2966 // necesary if std_entry is also a backward branch target because | |
2967 // then phi functions may be necessary in the header block. It's | |
2968 // also necessary when profiling so that there's a single block that | |
2969 // can increment the interpreter_invocation_count. | |
2970 BlockBegin* new_header_block; | |
1783 | 2971 if (std_entry->number_of_preds() > 0 || count_invocations() || count_backedges()) { |
2972 new_header_block = header_block(std_entry, BlockBegin::std_entry_flag, state); | |
2973 } else { | |
0 | 2974 new_header_block = std_entry; |
2975 } | |
2976 | |
2977 // setup start block (root for the IR graph) | |
2978 Base* base = | |
2979 new Base( | |
2980 new_header_block, | |
2981 osr_entry | |
2982 ); | |
2983 start->set_next(base, 0); | |
2984 start->set_end(base); | |
2985 // create & setup state for start block | |
1819 | 2986 start->set_state(state->copy(ValueStack::StateAfter, std_entry->bci())); |
2987 base->set_state(state->copy(ValueStack::StateAfter, std_entry->bci())); | |
0 | 2988 |
2989 if (base->std_entry()->state() == NULL) { | |
2990 // setup states for header blocks | |
2991 base->std_entry()->merge(state); | |
2992 } | |
2993 | |
2994 assert(base->std_entry()->state() != NULL, ""); | |
2995 return start; | |
2996 } | |
2997 | |
2998 | |
2999 void GraphBuilder::setup_osr_entry_block() { | |
3000 assert(compilation()->is_osr_compile(), "only for osrs"); | |
3001 | |
3002 int osr_bci = compilation()->osr_bci(); | |
3003 ciBytecodeStream s(method()); | |
3004 s.reset_to_bci(osr_bci); | |
3005 s.next(); | |
3006 scope_data()->set_stream(&s); | |
3007 | |
3008 // create a new block to be the osr setup code | |
3009 _osr_entry = new BlockBegin(osr_bci); | |
3010 _osr_entry->set(BlockBegin::osr_entry_flag); | |
3011 _osr_entry->set_depth_first_number(0); | |
3012 BlockBegin* target = bci2block()->at(osr_bci); | |
3013 assert(target != NULL && target->is_set(BlockBegin::osr_entry_flag), "must be there"); | |
3014 // the osr entry has no values for locals | |
3015 ValueStack* state = target->state()->copy(); | |
3016 _osr_entry->set_state(state); | |
3017 | |
3018 kill_all(); | |
3019 _block = _osr_entry; | |
3020 _state = _osr_entry->state()->copy(); | |
1819 | 3021 assert(_state->bci() == osr_bci, "mismatch"); |
0 | 3022 _last = _osr_entry; |
3023 Value e = append(new OsrEntry()); | |
3024 e->set_needs_null_check(false); | |
3025 | |
3026 // OSR buffer is | |
3027 // | |
3028 // locals[nlocals-1..0] | |
3029 // monitors[number_of_locks-1..0] | |
3030 // | |
3031 // locals is a direct copy of the interpreter frame so in the osr buffer | |
3032 // so first slot in the local array is the last local from the interpreter | |
3033 // and last slot is local[0] (receiver) from the interpreter | |
3034 // | |
3035 // Similarly with locks. The first lock slot in the osr buffer is the nth lock | |
3036 // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock | |
3037 // in the interpreter frame (the method lock if a sync method) | |
3038 | |
3039 // Initialize monitors in the compiled activation. | |
3040 | |
3041 int index; | |
3042 Value local; | |
3043 | |
3044 // find all the locals that the interpreter thinks contain live oops | |
3045 const BitMap live_oops = method()->live_local_oops_at_bci(osr_bci); | |
3046 | |
3047 // compute the offset into the locals so that we can treat the buffer | |
3048 // as if the locals were still in the interpreter frame | |
3049 int locals_offset = BytesPerWord * (method()->max_locals() - 1); | |
3050 for_each_local_value(state, index, local) { | |
3051 int offset = locals_offset - (index + local->type()->size() - 1) * BytesPerWord; | |
3052 Value get; | |
3053 if (local->type()->is_object_kind() && !live_oops.at(index)) { | |
3054 // The interpreter thinks this local is dead but the compiler | |
3055 // doesn't so pretend that the interpreter passed in null. | |
3056 get = append(new Constant(objectNull)); | |
3057 } else { | |
3058 get = append(new UnsafeGetRaw(as_BasicType(local->type()), e, | |
3059 append(new Constant(new IntConstant(offset))), | |
3060 0, | |
2002 | 3061 true /*unaligned*/, true /*wide*/)); |
0 | 3062 } |
3063 _state->store_local(index, get); | |
3064 } | |
3065 | |
3066 // the storage for the OSR buffer is freed manually in the LIRGenerator. | |
3067 | |
3068 assert(state->caller_state() == NULL, "should be top scope"); | |
3069 state->clear_locals(); | |
3070 Goto* g = new Goto(target, false); | |
3071 append(g); | |
3072 _osr_entry->set_end(g); | |
3073 target->merge(_osr_entry->end()->state()); | |
3074 | |
3075 scope_data()->set_stream(NULL); | |
3076 } | |
3077 | |
3078 | |
3079 ValueStack* GraphBuilder::state_at_entry() { | |
1819 | 3080 ValueStack* state = new ValueStack(scope(), NULL); |
0 | 3081 |
3082 // Set up locals for receiver | |
3083 int idx = 0; | |
3084 if (!method()->is_static()) { | |
3085 // we should always see the receiver | |
2446 | 3086 state->store_local(idx, new Local(method()->holder(), objectType, idx)); |
0 | 3087 idx = 1; |
3088 } | |
3089 | |
3090 // Set up locals for incoming arguments | |
3091 ciSignature* sig = method()->signature(); | |
3092 for (int i = 0; i < sig->count(); i++) { | |
3093 ciType* type = sig->type_at(i); | |
3094 BasicType basic_type = type->basic_type(); | |
3095 // don't allow T_ARRAY to propagate into locals types | |
3096 if (basic_type == T_ARRAY) basic_type = T_OBJECT; | |
3097 ValueType* vt = as_ValueType(basic_type); | |
2446 | 3098 state->store_local(idx, new Local(type, vt, idx)); |
0 | 3099 idx += type->size(); |
3100 } | |
3101 | |
3102 // lock synchronized method | |
3103 if (method()->is_synchronized()) { | |
1819 | 3104 state->lock(NULL); |
0 | 3105 } |
3106 | |
3107 return state; | |
3108 } | |
3109 | |
3110 | |
3111 GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) | |
3112 : _scope_data(NULL) | |
3113 , _instruction_count(0) | |
3114 , _osr_entry(NULL) | |
3115 , _memory(new MemoryBuffer()) | |
3116 , _compilation(compilation) | |
3117 , _inline_bailout_msg(NULL) | |
3118 { | |
3119 int osr_bci = compilation->osr_bci(); | |
3120 | |
3121 // determine entry points and bci2block mapping | |
3122 BlockListBuilder blm(compilation, scope, osr_bci); | |
3123 CHECK_BAILOUT(); | |
3124 | |
3125 BlockList* bci2block = blm.bci2block(); | |
3126 BlockBegin* start_block = bci2block->at(0); | |
3127 | |
3128 push_root_scope(scope, bci2block, start_block); | |
3129 | |
3130 // setup state for std entry | |
3131 _initial_state = state_at_entry(); | |
3132 start_block->merge(_initial_state); | |
3133 | |
3134 // complete graph | |
3135 _vmap = new ValueMap(); | |
3136 switch (scope->method()->intrinsic_id()) { | |
3137 case vmIntrinsics::_dabs : // fall through | |
3138 case vmIntrinsics::_dsqrt : // fall through | |
3139 case vmIntrinsics::_dsin : // fall through | |
3140 case vmIntrinsics::_dcos : // fall through | |
3141 case vmIntrinsics::_dtan : // fall through | |
3142 case vmIntrinsics::_dlog : // fall through | |
3143 case vmIntrinsics::_dlog10 : // fall through | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3144 case vmIntrinsics::_dexp : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3145 case vmIntrinsics::_dpow : // fall through |
0 | 3146 { |
3147 // Compiles where the root method is an intrinsic need a special | |
3148 // compilation environment because the bytecodes for the method | |
3149 // shouldn't be parsed during the compilation, only the special | |
3150 // Intrinsic node should be emitted. If this isn't done the the | |
3151 // code for the inlined version will be different than the root | |
3152 // compiled version which could lead to monotonicity problems on | |
3153 // intel. | |
3154 | |
3155 // Set up a stream so that appending instructions works properly. | |
3156 ciBytecodeStream s(scope->method()); | |
3157 s.reset_to_bci(0); | |
3158 scope_data()->set_stream(&s); | |
3159 s.next(); | |
3160 | |
3161 // setup the initial block state | |
3162 _block = start_block; | |
1819 | 3163 _state = start_block->state()->copy_for_parsing(); |
0 | 3164 _last = start_block; |
3165 load_local(doubleType, 0); | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3166 if (scope->method()->intrinsic_id() == vmIntrinsics::_dpow) { |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3167 load_local(doubleType, 2); |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3168 } |
0 | 3169 |
3170 // Emit the intrinsic node. | |
3171 bool result = try_inline_intrinsics(scope->method()); | |
3172 if (!result) BAILOUT("failed to inline intrinsic"); | |
3173 method_return(dpop()); | |
3174 | |
3175 // connect the begin and end blocks and we're all done. | |
3176 BlockEnd* end = last()->as_BlockEnd(); | |
3177 block()->set_end(end); | |
3178 break; | |
3179 } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3180 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3181 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3182 { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3183 { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3184 // With java.lang.ref.reference.get() we must go through the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3185 // intrinsic - when G1 is enabled - even when get() is the root |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3186 // method of the compile so that, if necessary, the value in |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3187 // the referent field of the reference object gets recorded by |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3188 // the pre-barrier code. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3189 // Specifically, if G1 is enabled, the value in the referent |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3190 // field is recorded by the G1 SATB pre barrier. This will |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3191 // result in the referent being marked live and the reference |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3192 // object removed from the list of discovered references during |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3193 // reference processing. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3194 |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3195 // Also we need intrinsic to prevent commoning reads from this field |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3196 // across safepoint since GC can change its value. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3197 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3198 // Set up a stream so that appending instructions works properly. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3199 ciBytecodeStream s(scope->method()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3200 s.reset_to_bci(0); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3201 scope_data()->set_stream(&s); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3202 s.next(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3203 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3204 // setup the initial block state |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3205 _block = start_block; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3206 _state = start_block->state()->copy_for_parsing(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3207 _last = start_block; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3208 load_local(objectType, 0); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3209 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3210 // Emit the intrinsic node. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3211 bool result = try_inline_intrinsics(scope->method()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3212 if (!result) BAILOUT("failed to inline intrinsic"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3213 method_return(apop()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3214 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3215 // connect the begin and end blocks and we're all done. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3216 BlockEnd* end = last()->as_BlockEnd(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3217 block()->set_end(end); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3218 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3219 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3220 // Otherwise, fall thru |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3221 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3222 |
0 | 3223 default: |
3224 scope_data()->add_to_work_list(start_block); | |
3225 iterate_all_blocks(); | |
3226 break; | |
3227 } | |
3228 CHECK_BAILOUT(); | |
3229 | |
3230 _start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state); | |
3231 | |
3232 eliminate_redundant_phis(_start); | |
3233 | |
3234 NOT_PRODUCT(if (PrintValueNumbering && Verbose) print_stats()); | |
3235 // for osr compile, bailout if some requirements are not fulfilled | |
3236 if (osr_bci != -1) { | |
3237 BlockBegin* osr_block = blm.bci2block()->at(osr_bci); | |
3238 assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile"); | |
3239 | |
3240 // check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points | |
3241 if (!osr_block->state()->stack_is_empty()) { | |
3242 BAILOUT("stack not empty at OSR entry point"); | |
3243 } | |
3244 } | |
3245 #ifndef PRODUCT | |
3246 if (PrintCompilation && Verbose) tty->print_cr("Created %d Instructions", _instruction_count); | |
3247 #endif | |
3248 } | |
3249 | |
3250 | |
1819 | 3251 ValueStack* GraphBuilder::copy_state_before() { |
3252 return copy_state_before_with_bci(bci()); | |
3253 } | |
3254 | |
3255 ValueStack* GraphBuilder::copy_state_exhandling() { | |
3256 return copy_state_exhandling_with_bci(bci()); | |
3257 } | |
3258 | |
3259 ValueStack* GraphBuilder::copy_state_for_exception() { | |
3260 return copy_state_for_exception_with_bci(bci()); | |
3261 } | |
3262 | |
3263 ValueStack* GraphBuilder::copy_state_before_with_bci(int bci) { | |
3264 return state()->copy(ValueStack::StateBefore, bci); | |
0 | 3265 } |
3266 | |
1819 | 3267 ValueStack* GraphBuilder::copy_state_exhandling_with_bci(int bci) { |
3268 if (!has_handler()) return NULL; | |
3269 return state()->copy(ValueStack::StateBefore, bci); | |
3270 } | |
3271 | |
3272 ValueStack* GraphBuilder::copy_state_for_exception_with_bci(int bci) { | |
3273 ValueStack* s = copy_state_exhandling_with_bci(bci); | |
3274 if (s == NULL) { | |
3275 if (_compilation->env()->jvmti_can_access_local_variables()) { | |
3276 s = state()->copy(ValueStack::ExceptionState, bci); | |
3277 } else { | |
3278 s = state()->copy(ValueStack::EmptyExceptionState, bci); | |
3279 } | |
3280 } | |
3281 return s; | |
3282 } | |
0 | 3283 |
3284 int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const { | |
3285 int recur_level = 0; | |
3286 for (IRScope* s = scope(); s != NULL; s = s->caller()) { | |
3287 if (s->method() == cur_callee) { | |
3288 ++recur_level; | |
3289 } | |
3290 } | |
3291 return recur_level; | |
3292 } | |
3293 | |
3294 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3295 bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Code bc, Value receiver) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3296 const char* msg = NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3297 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3298 // clear out any existing inline bailout condition |
0 | 3299 clear_inline_bailout(); |
3300 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3301 // exclude methods we don't want to inline |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3302 msg = should_not_inline(callee); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3303 if (msg != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3304 print_inlining(callee, msg, /*success*/ false); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3305 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3306 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3307 |
6892
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
3308 // method handle invokes |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
3309 if (callee->is_method_handle_intrinsic()) { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
3310 return try_method_handle_inline(callee); |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
3311 } |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
3312 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3313 // handle intrinsics |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3314 if (callee->intrinsic_id() != vmIntrinsics::_none) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3315 if (try_inline_intrinsics(callee)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3316 print_inlining(callee, "intrinsic"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3317 return true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3318 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3319 // try normal inlining |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3320 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3321 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3322 // certain methods cannot be parsed at all |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3323 msg = check_can_parse(callee); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3324 if (msg != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3325 print_inlining(callee, msg, /*success*/ false); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3326 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3327 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3328 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3329 // If bytecode not set use the current one. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3330 if (bc == Bytecodes::_illegal) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3331 bc = code(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3332 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3333 if (try_inline_full(callee, holder_known, bc, receiver)) |
0 | 3334 return true; |
7603 | 3335 |
3336 // Entire compilation could fail during try_inline_full call. | |
3337 // In that case printing inlining decision info is useless. | |
3338 if (!bailed_out()) | |
3339 print_inlining(callee, _inline_bailout_msg, /*success*/ false); | |
3340 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3341 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3342 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3343 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3344 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3345 const char* GraphBuilder::check_can_parse(ciMethod* callee) const { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3346 // Certain methods cannot be parsed at all: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3347 if ( callee->is_native()) return "native method"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3348 if ( callee->is_abstract()) return "abstract method"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3349 if (!callee->can_be_compiled()) return "not compilable (disabled)"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3350 return NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3351 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3352 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3353 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3354 // negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3355 const char* GraphBuilder::should_not_inline(ciMethod* callee) const { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3356 if ( callee->should_exclude()) return "excluded by CompilerOracle"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3357 if ( callee->should_not_inline()) return "disallowed by CompilerOracle"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3358 if ( callee->dont_inline()) return "don't inline by annotation"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3359 return NULL; |
0 | 3360 } |
3361 | |
3362 | |
3363 bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { | |
1540
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3364 if (callee->is_synchronized()) { |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3365 // We don't currently support any synchronized intrinsics |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3366 return false; |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3367 } |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3368 |
0 | 3369 // callee seems like a good candidate |
3370 // determine id | |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3371 vmIntrinsics::ID id = callee->intrinsic_id(); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3372 if (!InlineNatives && id != vmIntrinsics::_Reference_get) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3373 // InlineNatives does not control Reference.get |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3374 INLINE_BAILOUT("intrinsic method inlining disabled"); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3375 } |
0 | 3376 bool preserves_state = false; |
3377 bool cantrap = true; | |
3378 switch (id) { | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3379 case vmIntrinsics::_arraycopy: |
0 | 3380 if (!InlineArrayCopy) return false; |
3381 break; | |
3382 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3383 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3384 case vmIntrinsics::_classID: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3385 case vmIntrinsics::_threadID: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3386 preserves_state = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3387 cantrap = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3388 break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3389 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3390 case vmIntrinsics::_counterTime: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3391 preserves_state = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3392 cantrap = false; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3393 break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3394 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3395 |
0 | 3396 case vmIntrinsics::_currentTimeMillis: |
3397 case vmIntrinsics::_nanoTime: | |
3398 preserves_state = true; | |
3399 cantrap = false; | |
3400 break; | |
3401 | |
3402 case vmIntrinsics::_floatToRawIntBits : | |
3403 case vmIntrinsics::_intBitsToFloat : | |
3404 case vmIntrinsics::_doubleToRawLongBits : | |
3405 case vmIntrinsics::_longBitsToDouble : | |
3406 if (!InlineMathNatives) return false; | |
3407 preserves_state = true; | |
3408 cantrap = false; | |
3409 break; | |
3410 | |
3411 case vmIntrinsics::_getClass : | |
6135 | 3412 case vmIntrinsics::_isInstance : |
0 | 3413 if (!InlineClassNatives) return false; |
3414 preserves_state = true; | |
3415 break; | |
3416 | |
3417 case vmIntrinsics::_currentThread : | |
3418 if (!InlineThreadNatives) return false; | |
3419 preserves_state = true; | |
3420 cantrap = false; | |
3421 break; | |
3422 | |
3423 case vmIntrinsics::_dabs : // fall through | |
3424 case vmIntrinsics::_dsqrt : // fall through | |
3425 case vmIntrinsics::_dsin : // fall through | |
3426 case vmIntrinsics::_dcos : // fall through | |
3427 case vmIntrinsics::_dtan : // fall through | |
3428 case vmIntrinsics::_dlog : // fall through | |
3429 case vmIntrinsics::_dlog10 : // fall through | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3430 case vmIntrinsics::_dexp : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3431 case vmIntrinsics::_dpow : // fall through |
0 | 3432 if (!InlineMathNatives) return false; |
3433 cantrap = false; | |
3434 preserves_state = true; | |
3435 break; | |
3436 | |
3437 // Use special nodes for Unsafe instructions so we can more easily | |
3438 // perform an address-mode optimization on the raw variants | |
3439 case vmIntrinsics::_getObject : return append_unsafe_get_obj(callee, T_OBJECT, false); | |
3440 case vmIntrinsics::_getBoolean: return append_unsafe_get_obj(callee, T_BOOLEAN, false); | |
3441 case vmIntrinsics::_getByte : return append_unsafe_get_obj(callee, T_BYTE, false); | |
3442 case vmIntrinsics::_getShort : return append_unsafe_get_obj(callee, T_SHORT, false); | |
3443 case vmIntrinsics::_getChar : return append_unsafe_get_obj(callee, T_CHAR, false); | |
3444 case vmIntrinsics::_getInt : return append_unsafe_get_obj(callee, T_INT, false); | |
3445 case vmIntrinsics::_getLong : return append_unsafe_get_obj(callee, T_LONG, false); | |
3446 case vmIntrinsics::_getFloat : return append_unsafe_get_obj(callee, T_FLOAT, false); | |
3447 case vmIntrinsics::_getDouble : return append_unsafe_get_obj(callee, T_DOUBLE, false); | |
3448 | |
3449 case vmIntrinsics::_putObject : return append_unsafe_put_obj(callee, T_OBJECT, false); | |
3450 case vmIntrinsics::_putBoolean: return append_unsafe_put_obj(callee, T_BOOLEAN, false); | |
3451 case vmIntrinsics::_putByte : return append_unsafe_put_obj(callee, T_BYTE, false); | |
3452 case vmIntrinsics::_putShort : return append_unsafe_put_obj(callee, T_SHORT, false); | |
3453 case vmIntrinsics::_putChar : return append_unsafe_put_obj(callee, T_CHAR, false); | |
3454 case vmIntrinsics::_putInt : return append_unsafe_put_obj(callee, T_INT, false); | |
3455 case vmIntrinsics::_putLong : return append_unsafe_put_obj(callee, T_LONG, false); | |
3456 case vmIntrinsics::_putFloat : return append_unsafe_put_obj(callee, T_FLOAT, false); | |
3457 case vmIntrinsics::_putDouble : return append_unsafe_put_obj(callee, T_DOUBLE, false); | |
3458 | |
3459 case vmIntrinsics::_getObjectVolatile : return append_unsafe_get_obj(callee, T_OBJECT, true); | |
3460 case vmIntrinsics::_getBooleanVolatile: return append_unsafe_get_obj(callee, T_BOOLEAN, true); | |
3461 case vmIntrinsics::_getByteVolatile : return append_unsafe_get_obj(callee, T_BYTE, true); | |
3462 case vmIntrinsics::_getShortVolatile : return append_unsafe_get_obj(callee, T_SHORT, true); | |
3463 case vmIntrinsics::_getCharVolatile : return append_unsafe_get_obj(callee, T_CHAR, true); | |
3464 case vmIntrinsics::_getIntVolatile : return append_unsafe_get_obj(callee, T_INT, true); | |
3465 case vmIntrinsics::_getLongVolatile : return append_unsafe_get_obj(callee, T_LONG, true); | |
3466 case vmIntrinsics::_getFloatVolatile : return append_unsafe_get_obj(callee, T_FLOAT, true); | |
3467 case vmIntrinsics::_getDoubleVolatile : return append_unsafe_get_obj(callee, T_DOUBLE, true); | |
3468 | |
3469 case vmIntrinsics::_putObjectVolatile : return append_unsafe_put_obj(callee, T_OBJECT, true); | |
3470 case vmIntrinsics::_putBooleanVolatile: return append_unsafe_put_obj(callee, T_BOOLEAN, true); | |
3471 case vmIntrinsics::_putByteVolatile : return append_unsafe_put_obj(callee, T_BYTE, true); | |
3472 case vmIntrinsics::_putShortVolatile : return append_unsafe_put_obj(callee, T_SHORT, true); | |
3473 case vmIntrinsics::_putCharVolatile : return append_unsafe_put_obj(callee, T_CHAR, true); | |
3474 case vmIntrinsics::_putIntVolatile : return append_unsafe_put_obj(callee, T_INT, true); | |
3475 case vmIntrinsics::_putLongVolatile : return append_unsafe_put_obj(callee, T_LONG, true); | |
3476 case vmIntrinsics::_putFloatVolatile : return append_unsafe_put_obj(callee, T_FLOAT, true); | |
3477 case vmIntrinsics::_putDoubleVolatile : return append_unsafe_put_obj(callee, T_DOUBLE, true); | |
3478 | |
3479 case vmIntrinsics::_getByte_raw : return append_unsafe_get_raw(callee, T_BYTE); | |
3480 case vmIntrinsics::_getShort_raw : return append_unsafe_get_raw(callee, T_SHORT); | |
3481 case vmIntrinsics::_getChar_raw : return append_unsafe_get_raw(callee, T_CHAR); | |
3482 case vmIntrinsics::_getInt_raw : return append_unsafe_get_raw(callee, T_INT); | |
3483 case vmIntrinsics::_getLong_raw : return append_unsafe_get_raw(callee, T_LONG); | |
3484 case vmIntrinsics::_getFloat_raw : return append_unsafe_get_raw(callee, T_FLOAT); | |
3485 case vmIntrinsics::_getDouble_raw : return append_unsafe_get_raw(callee, T_DOUBLE); | |
3486 | |
3487 case vmIntrinsics::_putByte_raw : return append_unsafe_put_raw(callee, T_BYTE); | |
3488 case vmIntrinsics::_putShort_raw : return append_unsafe_put_raw(callee, T_SHORT); | |
3489 case vmIntrinsics::_putChar_raw : return append_unsafe_put_raw(callee, T_CHAR); | |
3490 case vmIntrinsics::_putInt_raw : return append_unsafe_put_raw(callee, T_INT); | |
3491 case vmIntrinsics::_putLong_raw : return append_unsafe_put_raw(callee, T_LONG); | |
3492 case vmIntrinsics::_putFloat_raw : return append_unsafe_put_raw(callee, T_FLOAT); | |
3493 case vmIntrinsics::_putDouble_raw : return append_unsafe_put_raw(callee, T_DOUBLE); | |
3494 | |
3495 case vmIntrinsics::_prefetchRead : return append_unsafe_prefetch(callee, false, false); | |
3496 case vmIntrinsics::_prefetchWrite : return append_unsafe_prefetch(callee, false, true); | |
3497 case vmIntrinsics::_prefetchReadStatic : return append_unsafe_prefetch(callee, true, false); | |
3498 case vmIntrinsics::_prefetchWriteStatic : return append_unsafe_prefetch(callee, true, true); | |
3499 | |
3500 case vmIntrinsics::_checkIndex : | |
3501 if (!InlineNIOCheckIndex) return false; | |
3502 preserves_state = true; | |
3503 break; | |
3504 case vmIntrinsics::_putOrderedObject : return append_unsafe_put_obj(callee, T_OBJECT, true); | |
3505 case vmIntrinsics::_putOrderedInt : return append_unsafe_put_obj(callee, T_INT, true); | |
3506 case vmIntrinsics::_putOrderedLong : return append_unsafe_put_obj(callee, T_LONG, true); | |
3507 | |
3508 case vmIntrinsics::_compareAndSwapLong: | |
3509 if (!VM_Version::supports_cx8()) return false; | |
3510 // fall through | |
3511 case vmIntrinsics::_compareAndSwapInt: | |
3512 case vmIntrinsics::_compareAndSwapObject: | |
3513 append_unsafe_CAS(callee); | |
3514 return true; | |
3515 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3516 case vmIntrinsics::_getAndAddInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3517 if (!VM_Version::supports_atomic_getadd4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3518 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3519 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3520 return append_unsafe_get_and_set_obj(callee, true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3521 case vmIntrinsics::_getAndAddLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3522 if (!VM_Version::supports_atomic_getadd8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3523 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3524 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3525 return append_unsafe_get_and_set_obj(callee, true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3526 case vmIntrinsics::_getAndSetInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3527 if (!VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3528 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3529 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3530 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3531 case vmIntrinsics::_getAndSetLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3532 if (!VM_Version::supports_atomic_getset8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3533 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3534 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3535 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3536 case vmIntrinsics::_getAndSetObject: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3537 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3538 if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3539 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3540 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3541 if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3542 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3543 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3544 #else |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3545 if (!VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3546 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3547 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3548 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3549 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3550 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3551 case vmIntrinsics::_Reference_get: |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3552 // Use the intrinsic version of Reference.get() so that the value in |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3553 // the referent field can be registered by the G1 pre-barrier code. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3554 // Also to prevent commoning reads from this field across safepoint |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3555 // since GC can change its value. |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3556 preserves_state = true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3557 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3558 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3559 case vmIntrinsics::_updateCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3560 case vmIntrinsics::_updateBytesCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3561 case vmIntrinsics::_updateByteBufferCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3562 if (!UseCRC32Intrinsics) return false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3563 cantrap = false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3564 preserves_state = true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3565 break; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3566 |
7425 | 3567 case vmIntrinsics::_loadFence : |
3568 case vmIntrinsics::_storeFence: | |
3569 case vmIntrinsics::_fullFence : | |
3570 break; | |
3571 | |
0 | 3572 default : return false; // do not inline |
3573 } | |
3574 // create intrinsic node | |
3575 const bool has_receiver = !callee->is_static(); | |
3576 ValueType* result_type = as_ValueType(callee->return_type()); | |
1819 | 3577 ValueStack* state_before = copy_state_for_exception(); |
0 | 3578 |
3579 Values* args = state()->pop_arguments(callee->arg_size()); | |
1783 | 3580 |
3581 if (is_profiling()) { | |
0 | 3582 // Don't profile in the special case where the root method |
3583 // is the intrinsic | |
3584 if (callee != method()) { | |
1783 | 3585 // Note that we'd collect profile data in this method if we wanted it. |
3586 compilation()->set_would_profile(true); | |
3587 if (profile_calls()) { | |
3588 Value recv = NULL; | |
3589 if (has_receiver) { | |
3590 recv = args->at(0); | |
3591 null_check(recv); | |
3592 } | |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
3593 profile_call(callee, recv, NULL, collect_args_for_profiling(args, callee, true), true); |
0 | 3594 } |
3595 } | |
3596 } | |
3597 | |
1819 | 3598 Intrinsic* result = new Intrinsic(result_type, id, args, has_receiver, state_before, |
0 | 3599 preserves_state, cantrap); |
3600 // append instruction & push result | |
3601 Value value = append_split(result); | |
3602 if (result_type != voidType) push(result_type, value); | |
3603 | |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
3604 if (callee != method() && profile_return() && result_type->is_object_kind()) { |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3605 profile_return_type(result, callee); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3606 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3607 |
0 | 3608 // done |
3609 return true; | |
3610 } | |
3611 | |
3612 | |
3613 bool GraphBuilder::try_inline_jsr(int jsr_dest_bci) { | |
3614 // Introduce a new callee continuation point - all Ret instructions | |
3615 // will be replaced with Gotos to this point. | |
3616 BlockBegin* cont = block_at(next_bci()); | |
3617 assert(cont != NULL, "continuation must exist (BlockListBuilder starts a new block after a jsr"); | |
3618 | |
3619 // Note: can not assign state to continuation yet, as we have to | |
3620 // pick up the state from the Ret instructions. | |
3621 | |
3622 // Push callee scope | |
3623 push_scope_for_jsr(cont, jsr_dest_bci); | |
3624 | |
3625 // Temporarily set up bytecode stream so we can append instructions | |
3626 // (only using the bci of this stream) | |
3627 scope_data()->set_stream(scope_data()->parent()->stream()); | |
3628 | |
3629 BlockBegin* jsr_start_block = block_at(jsr_dest_bci); | |
3630 assert(jsr_start_block != NULL, "jsr start block must exist"); | |
3631 assert(!jsr_start_block->is_set(BlockBegin::was_visited_flag), "should not have visited jsr yet"); | |
3632 Goto* goto_sub = new Goto(jsr_start_block, false); | |
3633 // Must copy state to avoid wrong sharing when parsing bytecodes | |
3634 assert(jsr_start_block->state() == NULL, "should have fresh jsr starting block"); | |
1819 | 3635 jsr_start_block->set_state(copy_state_before_with_bci(jsr_dest_bci)); |
0 | 3636 append(goto_sub); |
3637 _block->set_end(goto_sub); | |
3638 _last = _block = jsr_start_block; | |
3639 | |
3640 // Clear out bytecode stream | |
3641 scope_data()->set_stream(NULL); | |
3642 | |
3643 scope_data()->add_to_work_list(jsr_start_block); | |
3644 | |
3645 // Ready to resume parsing in subroutine | |
3646 iterate_all_blocks(); | |
3647 | |
3648 // If we bailed out during parsing, return immediately (this is bad news) | |
3649 CHECK_BAILOUT_(false); | |
3650 | |
3651 // Detect whether the continuation can actually be reached. If not, | |
3652 // it has not had state set by the join() operations in | |
3653 // iterate_bytecodes_for_block()/ret() and we should not touch the | |
3654 // iteration state. The calling activation of | |
3655 // iterate_bytecodes_for_block will then complete normally. | |
3656 if (cont->state() != NULL) { | |
3657 if (!cont->is_set(BlockBegin::was_visited_flag)) { | |
3658 // add continuation to work list instead of parsing it immediately | |
3659 scope_data()->parent()->add_to_work_list(cont); | |
3660 } | |
3661 } | |
3662 | |
3663 assert(jsr_continuation() == cont, "continuation must not have changed"); | |
3664 assert(!jsr_continuation()->is_set(BlockBegin::was_visited_flag) || | |
3665 jsr_continuation()->is_set(BlockBegin::parser_loop_header_flag), | |
3666 "continuation can only be visited in case of backward branches"); | |
3667 assert(_last && _last->as_BlockEnd(), "block must have end"); | |
3668 | |
3669 // continuation is in work list, so end iteration of current block | |
3670 _skip_block = true; | |
3671 pop_scope_for_jsr(); | |
3672 | |
3673 return true; | |
3674 } | |
3675 | |
3676 | |
3677 // Inline the entry of a synchronized method as a monitor enter and | |
3678 // register the exception handler which releases the monitor if an | |
3679 // exception is thrown within the callee. Note that the monitor enter | |
3680 // cannot throw an exception itself, because the receiver is | |
3681 // guaranteed to be non-null by the explicit null check at the | |
3682 // beginning of inlining. | |
3683 void GraphBuilder::inline_sync_entry(Value lock, BlockBegin* sync_handler) { | |
3684 assert(lock != NULL && sync_handler != NULL, "lock or handler missing"); | |
3685 | |
3686 monitorenter(lock, SynchronizationEntryBCI); | |
3687 assert(_last->as_MonitorEnter() != NULL, "monitor enter expected"); | |
3688 _last->set_needs_null_check(false); | |
3689 | |
3690 sync_handler->set(BlockBegin::exception_entry_flag); | |
3691 sync_handler->set(BlockBegin::is_on_work_list_flag); | |
3692 | |
3693 ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); | |
3694 XHandler* h = new XHandler(desc); | |
3695 h->set_entry_block(sync_handler); | |
3696 scope_data()->xhandlers()->append(h); | |
3697 scope_data()->set_has_handler(); | |
3698 } | |
3699 | |
3700 | |
3701 // If an exception is thrown and not handled within an inlined | |
3702 // synchronized method, the monitor must be released before the | |
3703 // exception is rethrown in the outer scope. Generate the appropriate | |
3704 // instructions here. | |
3705 void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler) { | |
3706 BlockBegin* orig_block = _block; | |
3707 ValueStack* orig_state = _state; | |
3708 Instruction* orig_last = _last; | |
3709 _last = _block = sync_handler; | |
3710 _state = sync_handler->state()->copy(); | |
3711 | |
3712 assert(sync_handler != NULL, "handler missing"); | |
3713 assert(!sync_handler->is_set(BlockBegin::was_visited_flag), "is visited here"); | |
3714 | |
3715 assert(lock != NULL || default_handler, "lock or handler missing"); | |
3716 | |
3717 XHandler* h = scope_data()->xhandlers()->remove_last(); | |
3718 assert(h->entry_block() == sync_handler, "corrupt list of handlers"); | |
3719 | |
3720 block()->set(BlockBegin::was_visited_flag); | |
3721 Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI); | |
3722 assert(exception->is_pinned(), "must be"); | |
3723 | |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3724 int bci = SynchronizationEntryBCI; |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3725 if (compilation()->env()->dtrace_method_probes()) { |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3726 // Report exit from inline methods. We don't have a stream here |
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3727 // so pass an explicit bci of SynchronizationEntryBCI. |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3728 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
3729 args->push(append_with_bci(new Constant(new MethodConstant(method())), bci)); |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3730 append_with_bci(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args), bci); |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3731 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3732 |
0 | 3733 if (lock) { |
3734 assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing"); | |
1819 | 3735 if (!lock->is_linked()) { |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3736 lock = append_with_bci(lock, bci); |
0 | 3737 } |
3738 | |
3739 // exit the monitor in the context of the synchronized method | |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3740 monitorexit(lock, bci); |
0 | 3741 |
3742 // exit the context of the synchronized method | |
3743 if (!default_handler) { | |
3744 pop_scope(); | |
1819 | 3745 bci = _state->caller_state()->bci(); |
3746 _state = _state->caller_state()->copy_for_parsing(); | |
0 | 3747 } |
3748 } | |
3749 | |
3750 // perform the throw as if at the the call site | |
3751 apush(exception); | |
3752 throw_op(bci); | |
3753 | |
3754 BlockEnd* end = last()->as_BlockEnd(); | |
3755 block()->set_end(end); | |
3756 | |
3757 _block = orig_block; | |
3758 _state = orig_state; | |
3759 _last = orig_last; | |
3760 } | |
3761 | |
3762 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3763 bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecodes::Code bc, Value receiver) { |
0 | 3764 assert(!callee->is_native(), "callee must not be native"); |
3791
2c359f27615c
7057120: Tiered: Allow C1 to inline methods with loops
iveresov
parents:
3255
diff
changeset
|
3765 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { |
2c359f27615c
7057120: Tiered: Allow C1 to inline methods with loops
iveresov
parents:
3255
diff
changeset
|
3766 INLINE_BAILOUT("inlining prohibited by policy"); |
1783 | 3767 } |
0 | 3768 // first perform tests of things it's not possible to inline |
3769 if (callee->has_exception_handlers() && | |
3770 !InlineMethodsWithExceptionHandlers) INLINE_BAILOUT("callee has exception handlers"); | |
3771 if (callee->is_synchronized() && | |
3772 !InlineSynchronizedMethods ) INLINE_BAILOUT("callee is synchronized"); | |
3773 if (!callee->holder()->is_initialized()) INLINE_BAILOUT("callee's klass not initialized yet"); | |
3774 if (!callee->has_balanced_monitors()) INLINE_BAILOUT("callee's monitors do not match"); | |
3775 | |
3776 // Proper inlining of methods with jsrs requires a little more work. | |
3777 if (callee->has_jsrs() ) INLINE_BAILOUT("jsrs not handled properly by inliner yet"); | |
3778 | |
3779 // When SSE2 is used on intel, then no special handling is needed | |
3780 // for strictfp because the enum-constant is fixed at compile time, | |
3781 // the check for UseSSE2 is needed here | |
3782 if (strict_fp_requires_explicit_rounding && UseSSE < 2 && method()->is_strict() != callee->is_strict()) { | |
3783 INLINE_BAILOUT("caller and callee have different strict fp requirements"); | |
3784 } | |
3785 | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3786 if (is_profiling() && !callee->ensure_method_data()) { |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3787 INLINE_BAILOUT("mdo allocation failed"); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3788 } |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3789 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3790 // now perform tests that are based on flag settings |
17819
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3791 if (callee->force_inline() || callee->should_inline()) { |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3792 if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel"); |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3793 if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3794 |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3795 const char* msg = ""; |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3796 if (callee->force_inline()) msg = "force inline by annotation"; |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3797 if (callee->should_inline()) msg = "force inline by CompileOracle"; |
f47fa50d9b9c
8035887: VM crashes trying to force inlining the recursive call
vlivanov
parents:
17618
diff
changeset
|
3798 print_inlining(callee, msg); |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3799 } else { |
7991
60bba1398c51
8005439: no message about inline method if it specifed by CompileCommand
vlivanov
parents:
7603
diff
changeset
|
3800 // use heuristic controls on inlining |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3801 if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3802 if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); |
3897
de847cac9235
7078382: JSR 292: don't count method handle adapters against inlining budgets
twisti
parents:
3844
diff
changeset
|
3803 if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3804 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3805 // don't inline throwable methods unless the inlining tree is rooted in a throwable class |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3806 if (callee->name() == ciSymbol::object_initializer_name() && |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3807 callee->holder()->is_subclass_of(ciEnv::current()->Throwable_klass())) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3808 // Throwable constructor call |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3809 IRScope* top = scope(); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3810 while (top->caller() != NULL) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3811 top = top->caller(); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3812 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3813 if (!top->method()->holder()->is_subclass_of(ciEnv::current()->Throwable_klass())) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3814 INLINE_BAILOUT("don't inline Throwable constructors"); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3815 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3816 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3817 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3818 if (compilation()->env()->num_inlined_bytecodes() > DesiredMethodLimit) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3819 INLINE_BAILOUT("total inlining greater than DesiredMethodLimit"); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3820 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3821 // printing |
6843 | 3822 print_inlining(callee); |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3823 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3824 |
0 | 3825 // NOTE: Bailouts from this point on, which occur at the |
3826 // GraphBuilder level, do not cause bailout just of the inlining but | |
3827 // in fact of the entire compilation. | |
3828 | |
3829 BlockBegin* orig_block = block(); | |
3830 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3831 const bool is_invokedynamic = bc == Bytecodes::_invokedynamic; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3832 const bool has_receiver = (bc != Bytecodes::_invokestatic && !is_invokedynamic); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3833 |
0 | 3834 const int args_base = state()->stack_size() - callee->arg_size(); |
3835 assert(args_base >= 0, "stack underflow during inlining"); | |
3836 | |
3837 // Insert null check if necessary | |
3838 Value recv = NULL; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3839 if (has_receiver) { |
0 | 3840 // note: null check must happen even if first instruction of callee does |
3841 // an implicit null check since the callee is in a different scope | |
3842 // and we must make sure exception handling does the right thing | |
3843 assert(!callee->is_static(), "callee must not be static"); | |
3844 assert(callee->arg_size() > 0, "must have at least a receiver"); | |
3845 recv = state()->stack_at(args_base); | |
3846 null_check(recv); | |
3847 } | |
3848 | |
1783 | 3849 if (is_profiling()) { |
3850 // Note that we'd collect profile data in this method if we wanted it. | |
3851 // this may be redundant here... | |
3852 compilation()->set_would_profile(true); | |
3853 | |
3854 if (profile_calls()) { | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3855 int start = 0; |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12882
diff
changeset
|
3856 Values* obj_args = args_list_for_profiling(callee, start, has_receiver); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3857 if (obj_args != NULL) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3858 int s = obj_args->size(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3859 // if called through method handle invoke, some arguments may have been popped |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3860 for (int i = args_base+start, j = 0; j < obj_args->size() && i < state()->stack_size(); ) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3861 Value v = state()->stack_at_inc(i); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3862 if (v->type()->is_object_kind()) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3863 obj_args->push(v); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3864 j++; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3865 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3866 } |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17819
diff
changeset
|
3867 check_args_for_profiling(obj_args, s); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3868 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
3869 profile_call(callee, recv, holder_known ? callee->holder() : NULL, obj_args, true); |
1783 | 3870 } |
0 | 3871 } |
3872 | |
3873 // Introduce a new callee continuation point - if the callee has | |
3874 // more than one return instruction or the return does not allow | |
3875 // fall-through of control flow, all return instructions of the | |
3876 // callee will need to be replaced by Goto's pointing to this | |
3877 // continuation point. | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3878 BlockBegin* cont = block_at(next_bci()); |
0 | 3879 bool continuation_existed = true; |
3880 if (cont == NULL) { | |
3881 cont = new BlockBegin(next_bci()); | |
3882 // low number so that continuation gets parsed as early as possible | |
3883 cont->set_depth_first_number(0); | |
3884 #ifndef PRODUCT | |
3885 if (PrintInitialBlockList) { | |
3886 tty->print_cr("CFG: created block %d (bci %d) as continuation for inline at bci %d", | |
3887 cont->block_id(), cont->bci(), bci()); | |
3888 } | |
3889 #endif | |
3890 continuation_existed = false; | |
3891 } | |
3892 // Record number of predecessors of continuation block before | |
3893 // inlining, to detect if inlined method has edges to its | |
3894 // continuation after inlining. | |
3895 int continuation_preds = cont->number_of_preds(); | |
3896 | |
3897 // Push callee scope | |
3898 push_scope(callee, cont); | |
3899 | |
3900 // the BlockListBuilder for the callee could have bailed out | |
7603 | 3901 if (bailed_out()) |
3902 return false; | |
0 | 3903 |
3904 // Temporarily set up bytecode stream so we can append instructions | |
3905 // (only using the bci of this stream) | |
3906 scope_data()->set_stream(scope_data()->parent()->stream()); | |
3907 | |
3908 // Pass parameters into callee state: add assignments | |
3909 // note: this will also ensure that all arguments are computed before being passed | |
3910 ValueStack* callee_state = state(); | |
1819 | 3911 ValueStack* caller_state = state()->caller_state(); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3912 for (int i = args_base; i < caller_state->stack_size(); ) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3913 const int arg_no = i - args_base; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3914 Value arg = caller_state->stack_at_inc(i); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3915 store_local(callee_state, arg, arg_no); |
0 | 3916 } |
3917 | |
3918 // Remove args from stack. | |
3919 // Note that we preserve locals state in case we can use it later | |
3920 // (see use of pop_scope() below) | |
3921 caller_state->truncate_stack(args_base); | |
1819 | 3922 assert(callee_state->stack_size() == 0, "callee stack must be empty"); |
0 | 3923 |
3924 Value lock; | |
3925 BlockBegin* sync_handler; | |
3926 | |
3927 // Inline the locking of the receiver if the callee is synchronized | |
3928 if (callee->is_synchronized()) { | |
3929 lock = callee->is_static() ? append(new Constant(new InstanceConstant(callee->holder()->java_mirror()))) | |
3930 : state()->local_at(0); | |
1819 | 3931 sync_handler = new BlockBegin(SynchronizationEntryBCI); |
0 | 3932 inline_sync_entry(lock, sync_handler); |
3933 } | |
3934 | |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3935 if (compilation()->env()->dtrace_method_probes()) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3936 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
3937 args->push(append(new Constant(new MethodConstant(method())))); |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3938 append(new RuntimeCall(voidType, "dtrace_method_entry", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), args)); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3939 } |
0 | 3940 |
4116
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3941 if (profile_inlined_calls()) { |
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3942 profile_invocation(callee, copy_state_before_with_bci(SynchronizationEntryBCI)); |
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3943 } |
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3944 |
0 | 3945 BlockBegin* callee_start_block = block_at(0); |
3946 if (callee_start_block != NULL) { | |
3947 assert(callee_start_block->is_set(BlockBegin::parser_loop_header_flag), "must be loop header"); | |
3948 Goto* goto_callee = new Goto(callee_start_block, false); | |
3949 // The state for this goto is in the scope of the callee, so use | |
3950 // the entry bci for the callee instead of the call site bci. | |
3951 append_with_bci(goto_callee, 0); | |
3952 _block->set_end(goto_callee); | |
3953 callee_start_block->merge(callee_state); | |
3954 | |
3955 _last = _block = callee_start_block; | |
3956 | |
3957 scope_data()->add_to_work_list(callee_start_block); | |
3958 } | |
3959 | |
3960 // Clear out bytecode stream | |
3961 scope_data()->set_stream(NULL); | |
3962 | |
20471
945284eb609f
8049532: LogCompilation: C1: inlining tree is flat (no depth is stored)
vlivanov
parents:
20344
diff
changeset
|
3963 CompileLog* log = compilation()->log(); |
945284eb609f
8049532: LogCompilation: C1: inlining tree is flat (no depth is stored)
vlivanov
parents:
20344
diff
changeset
|
3964 if (log != NULL) log->head("parse method='%d'", log->identify(callee)); |
945284eb609f
8049532: LogCompilation: C1: inlining tree is flat (no depth is stored)
vlivanov
parents:
20344
diff
changeset
|
3965 |
0 | 3966 // Ready to resume parsing in callee (either in the same block we |
3967 // were in before or in the callee's start block) | |
3968 iterate_all_blocks(callee_start_block == NULL); | |
3969 | |
20471
945284eb609f
8049532: LogCompilation: C1: inlining tree is flat (no depth is stored)
vlivanov
parents:
20344
diff
changeset
|
3970 if (log != NULL) log->done("parse"); |
945284eb609f
8049532: LogCompilation: C1: inlining tree is flat (no depth is stored)
vlivanov
parents:
20344
diff
changeset
|
3971 |
0 | 3972 // If we bailed out during parsing, return immediately (this is bad news) |
7603 | 3973 if (bailed_out()) |
3974 return false; | |
0 | 3975 |
3976 // iterate_all_blocks theoretically traverses in random order; in | |
3977 // practice, we have only traversed the continuation if we are | |
3978 // inlining into a subroutine | |
3979 assert(continuation_existed || | |
3980 !continuation()->is_set(BlockBegin::was_visited_flag), | |
3981 "continuation should not have been parsed yet if we created it"); | |
3982 | |
3983 // At this point we are almost ready to return and resume parsing of | |
3984 // the caller back in the GraphBuilder. The only thing we want to do | |
3985 // first is an optimization: during parsing of the callee we | |
3986 // generated at least one Goto to the continuation block. If we | |
3987 // generated exactly one, and if the inlined method spanned exactly | |
3988 // one block (and we didn't have to Goto its entry), then we snip | |
3989 // off the Goto to the continuation, allowing control to fall | |
3990 // through back into the caller block and effectively performing | |
3991 // block merging. This allows load elimination and CSE to take place | |
3992 // across multiple callee scopes if they are relatively simple, and | |
3993 // is currently essential to making inlining profitable. | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3994 if (num_returns() == 1 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3995 && block() == orig_block |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3996 && block() == inline_cleanup_block()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3997 _last = inline_cleanup_return_prev(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3998 _state = inline_cleanup_state(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3999 } else if (continuation_preds == cont->number_of_preds()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4000 // Inlining caused that the instructions after the invoke in the |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4001 // caller are not reachable any more. So skip filling this block |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4002 // with instructions! |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4003 assert(cont == continuation(), ""); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4004 assert(_last && _last->as_BlockEnd(), ""); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4005 _skip_block = true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4006 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4007 // Resume parsing in continuation block unless it was already parsed. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4008 // Note that if we don't change _last here, iteration in |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4009 // iterate_bytecodes_for_block will stop when we return. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4010 if (!continuation()->is_set(BlockBegin::was_visited_flag)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4011 // add continuation to work list instead of parsing it immediately |
0 | 4012 assert(_last && _last->as_BlockEnd(), ""); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4013 scope_data()->parent()->add_to_work_list(continuation()); |
0 | 4014 _skip_block = true; |
4015 } | |
4016 } | |
4017 | |
4018 // Fill the exception handler for synchronized methods with instructions | |
4019 if (callee->is_synchronized() && sync_handler->state() != NULL) { | |
4020 fill_sync_handler(lock, sync_handler); | |
4021 } else { | |
4022 pop_scope(); | |
4023 } | |
4024 | |
4025 compilation()->notice_inlined_method(callee); | |
4026 | |
4027 return true; | |
4028 } | |
4029 | |
4030 | |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
4031 bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4032 ValueStack* state_before = state()->copy_for_parsing(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4033 vmIntrinsics::ID iid = callee->intrinsic_id(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4034 switch (iid) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4035 case vmIntrinsics::_invokeBasic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4036 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4037 // get MethodHandle receiver |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4038 const int args_base = state()->stack_size() - callee->arg_size(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4039 ValueType* type = state()->stack_at(args_base)->type(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4040 if (type->is_constant()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4041 ciMethod* target = type->as_ObjectType()->constant_value()->as_method_handle()->get_vmtarget(); |
6892
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4042 // We don't do CHA here so only inline static and statically bindable methods. |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4043 if (target->is_static() || target->can_be_statically_bound()) { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4044 Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4045 if (try_inline(target, /*holder_known*/ true, bc)) { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4046 return true; |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4047 } |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4048 } else { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4049 print_inlining(target, "not static or statically bindable", /*success*/ false); |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4050 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4051 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4052 print_inlining(callee, "receiver not constant", /*success*/ false); |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4053 } |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4054 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4055 break; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4056 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4057 case vmIntrinsics::_linkToVirtual: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4058 case vmIntrinsics::_linkToStatic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4059 case vmIntrinsics::_linkToSpecial: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4060 case vmIntrinsics::_linkToInterface: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4061 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4062 // pop MemberName argument |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4063 const int args_base = state()->stack_size() - callee->arg_size(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4064 ValueType* type = apop()->type(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4065 if (type->is_constant()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4066 ciMethod* target = type->as_ObjectType()->constant_value()->as_member_name()->get_vmtarget(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4067 // If the target is another method handle invoke try recursivly to get |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4068 // a better target. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4069 if (target->is_method_handle_intrinsic()) { |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
4070 if (try_method_handle_inline(target)) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4071 return true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4072 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4073 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4074 ciSignature* signature = target->signature(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4075 const int receiver_skip = target->is_static() ? 0 : 1; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4076 // Cast receiver to its type. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4077 if (!target->is_static()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4078 ciKlass* tk = signature->accessing_klass(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4079 Value obj = state()->stack_at(args_base); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4080 if (obj->exact_type() == NULL && |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4081 obj->declared_type() != tk && tk != compilation()->env()->Object_klass()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4082 TypeCast* c = new TypeCast(tk, obj, state_before); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4083 append(c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4084 state()->stack_at_put(args_base, c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4085 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4086 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4087 // Cast reference arguments to its type. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4088 for (int i = 0, j = 0; i < signature->count(); i++) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4089 ciType* t = signature->type_at(i); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4090 if (t->is_klass()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4091 ciKlass* tk = t->as_klass(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4092 Value obj = state()->stack_at(args_base + receiver_skip + j); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4093 if (obj->exact_type() == NULL && |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4094 obj->declared_type() != tk && tk != compilation()->env()->Object_klass()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4095 TypeCast* c = new TypeCast(t, obj, state_before); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4096 append(c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4097 state()->stack_at_put(args_base + receiver_skip + j, c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4098 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4099 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4100 j += t->size(); // long and double take two slots |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4101 } |
6892
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4102 // We don't do CHA here so only inline static and statically bindable methods. |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4103 if (target->is_static() || target->can_be_statically_bound()) { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4104 Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4105 if (try_inline(target, /*holder_known*/ true, bc)) { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4106 return true; |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4107 } |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4108 } else { |
fd1d564dd460
8000821: JSR 292: C1 fails to call virtual method (JRUBY-6920)
twisti
parents:
6843
diff
changeset
|
4109 print_inlining(target, "not static or statically bindable", /*success*/ false); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4110 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4111 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4112 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4113 print_inlining(callee, "MemberName not constant", /*success*/ false); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4114 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4115 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4116 break; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4117 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4118 default: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4119 fatal(err_msg("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4120 break; |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4121 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4122 set_state(state_before); |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4123 return false; |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4124 } |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4125 |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
4126 |
0 | 4127 void GraphBuilder::inline_bailout(const char* msg) { |
4128 assert(msg != NULL, "inline bailout msg must exist"); | |
4129 _inline_bailout_msg = msg; | |
4130 } | |
4131 | |
4132 | |
4133 void GraphBuilder::clear_inline_bailout() { | |
4134 _inline_bailout_msg = NULL; | |
4135 } | |
4136 | |
4137 | |
4138 void GraphBuilder::push_root_scope(IRScope* scope, BlockList* bci2block, BlockBegin* start) { | |
4139 ScopeData* data = new ScopeData(NULL); | |
4140 data->set_scope(scope); | |
4141 data->set_bci2block(bci2block); | |
4142 _scope_data = data; | |
4143 _block = start; | |
4144 } | |
4145 | |
4146 | |
4147 void GraphBuilder::push_scope(ciMethod* callee, BlockBegin* continuation) { | |
4148 IRScope* callee_scope = new IRScope(compilation(), scope(), bci(), callee, -1, false); | |
4149 scope()->add_callee(callee_scope); | |
4150 | |
4151 BlockListBuilder blb(compilation(), callee_scope, -1); | |
4152 CHECK_BAILOUT(); | |
4153 | |
4154 if (!blb.bci2block()->at(0)->is_set(BlockBegin::parser_loop_header_flag)) { | |
4155 // this scope can be inlined directly into the caller so remove | |
4156 // the block at bci 0. | |
4157 blb.bci2block()->at_put(0, NULL); | |
4158 } | |
4159 | |
1819 | 4160 set_state(new ValueStack(callee_scope, state()->copy(ValueStack::CallerState, bci()))); |
0 | 4161 |
4162 ScopeData* data = new ScopeData(scope_data()); | |
4163 data->set_scope(callee_scope); | |
4164 data->set_bci2block(blb.bci2block()); | |
4165 data->set_continuation(continuation); | |
4166 _scope_data = data; | |
4167 } | |
4168 | |
4169 | |
4170 void GraphBuilder::push_scope_for_jsr(BlockBegin* jsr_continuation, int jsr_dest_bci) { | |
4171 ScopeData* data = new ScopeData(scope_data()); | |
4172 data->set_parsing_jsr(); | |
4173 data->set_jsr_entry_bci(jsr_dest_bci); | |
4174 data->set_jsr_return_address_local(-1); | |
4175 // Must clone bci2block list as we will be mutating it in order to | |
4176 // properly clone all blocks in jsr region as well as exception | |
4177 // handlers containing rets | |
4178 BlockList* new_bci2block = new BlockList(bci2block()->length()); | |
4179 new_bci2block->push_all(bci2block()); | |
4180 data->set_bci2block(new_bci2block); | |
4181 data->set_scope(scope()); | |
4182 data->setup_jsr_xhandlers(); | |
4183 data->set_continuation(continuation()); | |
4184 data->set_jsr_continuation(jsr_continuation); | |
4185 _scope_data = data; | |
4186 } | |
4187 | |
4188 | |
4189 void GraphBuilder::pop_scope() { | |
4190 int number_of_locks = scope()->number_of_locks(); | |
4191 _scope_data = scope_data()->parent(); | |
4192 // accumulate minimum number of monitor slots to be reserved | |
4193 scope()->set_min_number_of_locks(number_of_locks); | |
4194 } | |
4195 | |
4196 | |
4197 void GraphBuilder::pop_scope_for_jsr() { | |
4198 _scope_data = scope_data()->parent(); | |
4199 } | |
4200 | |
4201 bool GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) { | |
4202 if (InlineUnsafeOps) { | |
4203 Values* args = state()->pop_arguments(callee->arg_size()); | |
4204 null_check(args->at(0)); | |
4205 Instruction* offset = args->at(2); | |
4206 #ifndef _LP64 | |
4207 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4208 #endif | |
4209 Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile)); | |
4210 push(op->type(), op); | |
4211 compilation()->set_has_unsafe_access(true); | |
4212 } | |
4213 return InlineUnsafeOps; | |
4214 } | |
4215 | |
4216 | |
4217 bool GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) { | |
4218 if (InlineUnsafeOps) { | |
4219 Values* args = state()->pop_arguments(callee->arg_size()); | |
4220 null_check(args->at(0)); | |
4221 Instruction* offset = args->at(2); | |
4222 #ifndef _LP64 | |
4223 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4224 #endif | |
4225 Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); | |
4226 compilation()->set_has_unsafe_access(true); | |
4227 kill_all(); | |
4228 } | |
4229 return InlineUnsafeOps; | |
4230 } | |
4231 | |
4232 | |
4233 bool GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) { | |
4234 if (InlineUnsafeOps) { | |
4235 Values* args = state()->pop_arguments(callee->arg_size()); | |
4236 null_check(args->at(0)); | |
4237 Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false)); | |
4238 push(op->type(), op); | |
4239 compilation()->set_has_unsafe_access(true); | |
4240 } | |
4241 return InlineUnsafeOps; | |
4242 } | |
4243 | |
4244 | |
4245 bool GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) { | |
4246 if (InlineUnsafeOps) { | |
4247 Values* args = state()->pop_arguments(callee->arg_size()); | |
4248 null_check(args->at(0)); | |
4249 Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2))); | |
4250 compilation()->set_has_unsafe_access(true); | |
4251 } | |
4252 return InlineUnsafeOps; | |
4253 } | |
4254 | |
4255 | |
4256 bool GraphBuilder::append_unsafe_prefetch(ciMethod* callee, bool is_static, bool is_store) { | |
4257 if (InlineUnsafeOps) { | |
4258 Values* args = state()->pop_arguments(callee->arg_size()); | |
4259 int obj_arg_index = 1; // Assume non-static case | |
4260 if (is_static) { | |
4261 obj_arg_index = 0; | |
4262 } else { | |
4263 null_check(args->at(0)); | |
4264 } | |
4265 Instruction* offset = args->at(obj_arg_index + 1); | |
4266 #ifndef _LP64 | |
4267 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4268 #endif | |
4269 Instruction* op = is_store ? append(new UnsafePrefetchWrite(args->at(obj_arg_index), offset)) | |
4270 : append(new UnsafePrefetchRead (args->at(obj_arg_index), offset)); | |
4271 compilation()->set_has_unsafe_access(true); | |
4272 } | |
4273 return InlineUnsafeOps; | |
4274 } | |
4275 | |
4276 | |
4277 void GraphBuilder::append_unsafe_CAS(ciMethod* callee) { | |
1819 | 4278 ValueStack* state_before = copy_state_for_exception(); |
0 | 4279 ValueType* result_type = as_ValueType(callee->return_type()); |
4280 assert(result_type->is_int(), "int result"); | |
4281 Values* args = state()->pop_arguments(callee->arg_size()); | |
4282 | |
4283 // Pop off some args to speically handle, then push back | |
4284 Value newval = args->pop(); | |
4285 Value cmpval = args->pop(); | |
4286 Value offset = args->pop(); | |
4287 Value src = args->pop(); | |
4288 Value unsafe_obj = args->pop(); | |
4289 | |
4290 // Separately handle the unsafe arg. It is not needed for code | |
4291 // generation, but must be null checked | |
4292 null_check(unsafe_obj); | |
4293 | |
4294 #ifndef _LP64 | |
4295 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4296 #endif | |
4297 | |
4298 args->push(src); | |
4299 args->push(offset); | |
4300 args->push(cmpval); | |
4301 args->push(newval); | |
4302 | |
4303 // An unsafe CAS can alias with other field accesses, but we don't | |
4304 // know which ones so mark the state as no preserved. This will | |
4305 // cause CSE to invalidate memory across it. | |
4306 bool preserves_state = false; | |
1819 | 4307 Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(), args, false, state_before, preserves_state); |
0 | 4308 append_split(result); |
4309 push(result_type, result); | |
4310 compilation()->set_has_unsafe_access(true); | |
4311 } | |
4312 | |
4313 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4314 void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) { |
6843 | 4315 CompileLog* log = compilation()->log(); |
4316 if (log != NULL) { | |
4317 if (success) { | |
4318 if (msg != NULL) | |
4319 log->inline_success(msg); | |
4320 else | |
4321 log->inline_success("receiver is statically known"); | |
4322 } else { | |
7603 | 4323 if (msg != NULL) |
4324 log->inline_fail(msg); | |
4325 else | |
4326 log->inline_fail("reason unknown"); | |
6843 | 4327 } |
4328 } | |
4329 | |
12295 | 4330 if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) { |
4331 return; | |
4332 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4333 CompileTask::print_inlining(callee, scope()->level(), bci(), msg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4334 if (success && CIPrintMethodCodes) { |
0 | 4335 callee->print_codes(); |
4336 } | |
4337 } | |
4338 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4339 bool GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4340 if (InlineUnsafeOps) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4341 Values* args = state()->pop_arguments(callee->arg_size()); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4342 BasicType t = callee->return_type()->basic_type(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4343 null_check(args->at(0)); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4344 Instruction* offset = args->at(2); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4345 #ifndef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4346 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4347 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4348 Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add)); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4349 compilation()->set_has_unsafe_access(true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4350 kill_all(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4351 push(op->type(), op); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4352 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4353 return InlineUnsafeOps; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4354 } |
0 | 4355 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4356 #ifndef PRODUCT |
0 | 4357 void GraphBuilder::print_stats() { |
4358 vmap()->print(); | |
4359 } | |
4360 #endif // PRODUCT | |
4361 | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
4362 void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder, Values* obj_args, bool inlined) { |
17618
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4363 assert(known_holder == NULL || (known_holder->is_instance_klass() && |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4364 (!known_holder->is_interface() || |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4365 ((ciInstanceKlass*)known_holder)->has_default_methods())), "should be default method"); |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4366 if (known_holder != NULL) { |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4367 if (known_holder->exact_klass() == NULL) { |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4368 known_holder = compilation()->cha_exact_type(known_holder); |
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4369 } |
13075
144b23411b51
8027632: assert(xtype->klass_is_exact()) failed: Should be exact at graphKit.cpp
roland
parents:
13021
diff
changeset
|
4370 } |
17618
f834ae379225
8028064: tiered may collect wrong receiver type at virtual call
roland
parents:
13075
diff
changeset
|
4371 |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12295
diff
changeset
|
4372 append(new ProfileCall(method(), bci(), callee, recv, known_holder, obj_args, inlined)); |
0 | 4373 } |
4374 | |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4375 void GraphBuilder::profile_return_type(Value ret, ciMethod* callee, ciMethod* m, int invoke_bci) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4376 assert((m == NULL) == (invoke_bci < 0), "invalid method and invalid bci together"); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4377 if (m == NULL) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4378 m = method(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4379 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4380 if (invoke_bci < 0) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4381 invoke_bci = bci(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4382 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4383 ciMethodData* md = m->method_data_or_null(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4384 ciProfileData* data = md->bci_to_data(invoke_bci); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4385 if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4386 append(new ProfileReturnType(m , invoke_bci, callee, ret)); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4387 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4388 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
4389 |
1825 | 4390 void GraphBuilder::profile_invocation(ciMethod* callee, ValueStack* state) { |
4391 append(new ProfileInvoke(callee, state)); | |
0 | 4392 } |