Mercurial > hg > truffle
annotate src/share/vm/c1/c1_GraphBuilder.cpp @ 6862:8a5ea0a9ccc4
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author | johnc |
---|---|
date | Sat, 06 Oct 2012 01:17:44 -0700 |
parents | 7eca5de9e0b6 |
children | c3e799c37717 |
rev | line source |
---|---|
0 | 1 /* |
4870
2f5980b127e3
7132180: JSR 292: C1 JVM crash with ClassValue/MethodHandle
twisti
parents:
4116
diff
changeset
|
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
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) { | |
1819 | 950 ValueStack* state_before = copy_state_for_exception(); |
0 | 951 Value index = ipop(); |
952 Value array = apop(); | |
953 Value length = NULL; | |
954 if (CSEArrayLength || | |
955 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || | |
956 (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { | |
1819 | 957 length = append(new ArrayLength(array, state_before)); |
0 | 958 } |
1819 | 959 push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before))); |
0 | 960 } |
961 | |
962 | |
963 void GraphBuilder::store_indexed(BasicType type) { | |
1819 | 964 ValueStack* state_before = copy_state_for_exception(); |
0 | 965 Value value = pop(as_ValueType(type)); |
966 Value index = ipop(); | |
967 Value array = apop(); | |
968 Value length = NULL; | |
969 if (CSEArrayLength || | |
970 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || | |
971 (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { | |
1819 | 972 length = append(new ArrayLength(array, state_before)); |
0 | 973 } |
1819 | 974 StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); |
0 | 975 append(result); |
459 | 976 _memory->store_value(value); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
977 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
978 if (type == T_OBJECT && is_profiling()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
979 // 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
|
980 compilation()->set_would_profile(true); |
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 (profile_checkcasts()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
983 result->set_profiled_method(method()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
984 result->set_profiled_bci(bci()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
985 result->set_should_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
986 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
987 } |
0 | 988 } |
989 | |
990 | |
991 void GraphBuilder::stack_op(Bytecodes::Code code) { | |
992 switch (code) { | |
993 case Bytecodes::_pop: | |
994 { state()->raw_pop(); | |
995 } | |
996 break; | |
997 case Bytecodes::_pop2: | |
998 { state()->raw_pop(); | |
999 state()->raw_pop(); | |
1000 } | |
1001 break; | |
1002 case Bytecodes::_dup: | |
1003 { Value w = state()->raw_pop(); | |
1004 state()->raw_push(w); | |
1005 state()->raw_push(w); | |
1006 } | |
1007 break; | |
1008 case Bytecodes::_dup_x1: | |
1009 { Value w1 = state()->raw_pop(); | |
1010 Value w2 = state()->raw_pop(); | |
1011 state()->raw_push(w1); | |
1012 state()->raw_push(w2); | |
1013 state()->raw_push(w1); | |
1014 } | |
1015 break; | |
1016 case Bytecodes::_dup_x2: | |
1017 { Value w1 = state()->raw_pop(); | |
1018 Value w2 = state()->raw_pop(); | |
1019 Value w3 = state()->raw_pop(); | |
1020 state()->raw_push(w1); | |
1021 state()->raw_push(w3); | |
1022 state()->raw_push(w2); | |
1023 state()->raw_push(w1); | |
1024 } | |
1025 break; | |
1026 case Bytecodes::_dup2: | |
1027 { Value w1 = state()->raw_pop(); | |
1028 Value w2 = state()->raw_pop(); | |
1029 state()->raw_push(w2); | |
1030 state()->raw_push(w1); | |
1031 state()->raw_push(w2); | |
1032 state()->raw_push(w1); | |
1033 } | |
1034 break; | |
1035 case Bytecodes::_dup2_x1: | |
1036 { Value w1 = state()->raw_pop(); | |
1037 Value w2 = state()->raw_pop(); | |
1038 Value w3 = state()->raw_pop(); | |
1039 state()->raw_push(w2); | |
1040 state()->raw_push(w1); | |
1041 state()->raw_push(w3); | |
1042 state()->raw_push(w2); | |
1043 state()->raw_push(w1); | |
1044 } | |
1045 break; | |
1046 case Bytecodes::_dup2_x2: | |
1047 { Value w1 = state()->raw_pop(); | |
1048 Value w2 = state()->raw_pop(); | |
1049 Value w3 = state()->raw_pop(); | |
1050 Value w4 = state()->raw_pop(); | |
1051 state()->raw_push(w2); | |
1052 state()->raw_push(w1); | |
1053 state()->raw_push(w4); | |
1054 state()->raw_push(w3); | |
1055 state()->raw_push(w2); | |
1056 state()->raw_push(w1); | |
1057 } | |
1058 break; | |
1059 case Bytecodes::_swap: | |
1060 { Value w1 = state()->raw_pop(); | |
1061 Value w2 = state()->raw_pop(); | |
1062 state()->raw_push(w1); | |
1063 state()->raw_push(w2); | |
1064 } | |
1065 break; | |
1066 default: | |
1067 ShouldNotReachHere(); | |
1068 break; | |
1069 } | |
1070 } | |
1071 | |
1072 | |
1819 | 1073 void GraphBuilder::arithmetic_op(ValueType* type, Bytecodes::Code code, ValueStack* state_before) { |
0 | 1074 Value y = pop(type); |
1075 Value x = pop(type); | |
1076 // NOTE: strictfp can be queried from current method since we don't | |
1077 // inline methods with differing strictfp bits | |
1819 | 1078 Value res = new ArithmeticOp(code, x, y, method()->is_strict(), state_before); |
0 | 1079 // Note: currently single-precision floating-point rounding on Intel is handled at the LIRGenerator level |
1080 res = append(res); | |
1081 if (method()->is_strict()) { | |
1082 res = round_fp(res); | |
1083 } | |
1084 push(type, res); | |
1085 } | |
1086 | |
1087 | |
1088 void GraphBuilder::negate_op(ValueType* type) { | |
1089 push(type, append(new NegateOp(pop(type)))); | |
1090 } | |
1091 | |
1092 | |
1093 void GraphBuilder::shift_op(ValueType* type, Bytecodes::Code code) { | |
1094 Value s = ipop(); | |
1095 Value x = pop(type); | |
1096 // try to simplify | |
1097 // Note: This code should go into the canonicalizer as soon as it can | |
1098 // can handle canonicalized forms that contain more than one node. | |
1099 if (CanonicalizeNodes && code == Bytecodes::_iushr) { | |
1100 // pattern: x >>> s | |
1101 IntConstant* s1 = s->type()->as_IntConstant(); | |
1102 if (s1 != NULL) { | |
1103 // pattern: x >>> s1, with s1 constant | |
1104 ShiftOp* l = x->as_ShiftOp(); | |
1105 if (l != NULL && l->op() == Bytecodes::_ishl) { | |
1106 // pattern: (a << b) >>> s1 | |
1107 IntConstant* s0 = l->y()->type()->as_IntConstant(); | |
1108 if (s0 != NULL) { | |
1109 // pattern: (a << s0) >>> s1 | |
1110 const int s0c = s0->value() & 0x1F; // only the low 5 bits are significant for shifts | |
1111 const int s1c = s1->value() & 0x1F; // only the low 5 bits are significant for shifts | |
1112 if (s0c == s1c) { | |
1113 if (s0c == 0) { | |
1114 // pattern: (a << 0) >>> 0 => simplify to: a | |
1115 ipush(l->x()); | |
1116 } else { | |
1117 // pattern: (a << s0c) >>> s0c => simplify to: a & m, with m constant | |
1118 assert(0 < s0c && s0c < BitsPerInt, "adjust code below to handle corner cases"); | |
1119 const int m = (1 << (BitsPerInt - s0c)) - 1; | |
1120 Value s = append(new Constant(new IntConstant(m))); | |
1121 ipush(append(new LogicOp(Bytecodes::_iand, l->x(), s))); | |
1122 } | |
1123 return; | |
1124 } | |
1125 } | |
1126 } | |
1127 } | |
1128 } | |
1129 // could not simplify | |
1130 push(type, append(new ShiftOp(code, x, s))); | |
1131 } | |
1132 | |
1133 | |
1134 void GraphBuilder::logic_op(ValueType* type, Bytecodes::Code code) { | |
1135 Value y = pop(type); | |
1136 Value x = pop(type); | |
1137 push(type, append(new LogicOp(code, x, y))); | |
1138 } | |
1139 | |
1140 | |
1141 void GraphBuilder::compare_op(ValueType* type, Bytecodes::Code code) { | |
1819 | 1142 ValueStack* state_before = copy_state_before(); |
0 | 1143 Value y = pop(type); |
1144 Value x = pop(type); | |
1145 ipush(append(new CompareOp(code, x, y, state_before))); | |
1146 } | |
1147 | |
1148 | |
1149 void GraphBuilder::convert(Bytecodes::Code op, BasicType from, BasicType to) { | |
1150 push(as_ValueType(to), append(new Convert(op, pop(as_ValueType(from)), as_ValueType(to)))); | |
1151 } | |
1152 | |
1153 | |
1154 void GraphBuilder::increment() { | |
1155 int index = stream()->get_index(); | |
1156 int delta = stream()->is_wide() ? (signed short)Bytes::get_Java_u2(stream()->cur_bcp() + 4) : (signed char)(stream()->cur_bcp()[2]); | |
1157 load_local(intType, index); | |
1158 ipush(append(new Constant(new IntConstant(delta)))); | |
1159 arithmetic_op(intType, Bytecodes::_iadd); | |
1160 store_local(intType, index); | |
1161 } | |
1162 | |
1163 | |
1164 void GraphBuilder::_goto(int from_bci, int to_bci) { | |
1783 | 1165 Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci); |
1166 if (is_profiling()) { | |
1167 compilation()->set_would_profile(true); | |
1168 x->set_profiled_bci(bci()); | |
3997
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1169 if (profile_branches()) { |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1170 x->set_profiled_method(method()); |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1171 x->set_should_profile(true); |
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1172 } |
1783 | 1173 } |
1174 append(x); | |
0 | 1175 } |
1176 | |
1177 | |
1178 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) { | |
1179 BlockBegin* tsux = block_at(stream()->get_dest()); | |
1180 BlockBegin* fsux = block_at(stream()->next_bci()); | |
1181 bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci(); | |
1783 | 1182 Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb)); |
1183 | |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1184 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
|
1185 (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
|
1186 (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
|
1187 "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
|
1188 |
1783 | 1189 if (is_profiling()) { |
1190 If* if_node = i->as_If(); | |
1191 if (if_node != NULL) { | |
1192 // Note that we'd collect profile data in this method if we wanted it. | |
1193 compilation()->set_would_profile(true); | |
1194 // At level 2 we need the proper bci to count backedges | |
1195 if_node->set_profiled_bci(bci()); | |
1196 if (profile_branches()) { | |
1197 // Successors can be rotated by the canonicalizer, check for this case. | |
1198 if_node->set_profiled_method(method()); | |
1199 if_node->set_should_profile(true); | |
1200 if (if_node->tsux() == fsux) { | |
1201 if_node->set_swapped(true); | |
1202 } | |
1203 } | |
1204 return; | |
1205 } | |
1206 | |
1207 // Check if this If was reduced to Goto. | |
1208 Goto *goto_node = i->as_Goto(); | |
1209 if (goto_node != NULL) { | |
1210 compilation()->set_would_profile(true); | |
3997
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3901
diff
changeset
|
1211 goto_node->set_profiled_bci(bci()); |
1783 | 1212 if (profile_branches()) { |
1213 goto_node->set_profiled_method(method()); | |
1214 goto_node->set_should_profile(true); | |
1215 // Find out which successor is used. | |
1216 if (goto_node->default_sux() == tsux) { | |
1217 goto_node->set_direction(Goto::taken); | |
1218 } else if (goto_node->default_sux() == fsux) { | |
1219 goto_node->set_direction(Goto::not_taken); | |
1220 } else { | |
1221 ShouldNotReachHere(); | |
1222 } | |
1223 } | |
1224 return; | |
1225 } | |
0 | 1226 } |
1227 } | |
1228 | |
1229 | |
1230 void GraphBuilder::if_zero(ValueType* type, If::Condition cond) { | |
1231 Value y = append(new Constant(intZero)); | |
1819 | 1232 ValueStack* state_before = copy_state_before(); |
0 | 1233 Value x = ipop(); |
1234 if_node(x, cond, y, state_before); | |
1235 } | |
1236 | |
1237 | |
1238 void GraphBuilder::if_null(ValueType* type, If::Condition cond) { | |
1239 Value y = append(new Constant(objectNull)); | |
1819 | 1240 ValueStack* state_before = copy_state_before(); |
0 | 1241 Value x = apop(); |
1242 if_node(x, cond, y, state_before); | |
1243 } | |
1244 | |
1245 | |
1246 void GraphBuilder::if_same(ValueType* type, If::Condition cond) { | |
1819 | 1247 ValueStack* state_before = copy_state_before(); |
0 | 1248 Value y = pop(type); |
1249 Value x = pop(type); | |
1250 if_node(x, cond, y, state_before); | |
1251 } | |
1252 | |
1253 | |
1254 void GraphBuilder::jsr(int dest) { | |
1255 // We only handle well-formed jsrs (those which are "block-structured"). | |
1256 // If the bytecodes are strange (jumping out of a jsr block) then we | |
1257 // might end up trying to re-parse a block containing a jsr which | |
1258 // has already been activated. Watch for this case and bail out. | |
1259 for (ScopeData* cur_scope_data = scope_data(); | |
1260 cur_scope_data != NULL && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope(); | |
1261 cur_scope_data = cur_scope_data->parent()) { | |
1262 if (cur_scope_data->jsr_entry_bci() == dest) { | |
1263 BAILOUT("too-complicated jsr/ret structure"); | |
1264 } | |
1265 } | |
1266 | |
1267 push(addressType, append(new Constant(new AddressConstant(next_bci())))); | |
1268 if (!try_inline_jsr(dest)) { | |
1269 return; // bailed out while parsing and inlining subroutine | |
1270 } | |
1271 } | |
1272 | |
1273 | |
1274 void GraphBuilder::ret(int local_index) { | |
1275 if (!parsing_jsr()) BAILOUT("ret encountered while not parsing subroutine"); | |
1276 | |
1277 if (local_index != scope_data()->jsr_return_address_local()) { | |
1278 BAILOUT("can not handle complicated jsr/ret constructs"); | |
1279 } | |
1280 | |
1281 // Rets simply become (NON-SAFEPOINT) gotos to the jsr continuation | |
1282 append(new Goto(scope_data()->jsr_continuation(), false)); | |
1283 } | |
1284 | |
1285 | |
1286 void GraphBuilder::table_switch() { | |
2142 | 1287 Bytecode_tableswitch sw(stream()); |
1288 const int l = sw.length(); | |
0 | 1289 if (CanonicalizeNodes && l == 1) { |
1290 // total of 2 successors => use If instead of switch | |
1291 // Note: This code should go into the canonicalizer as soon as it can | |
1292 // can handle canonicalized forms that contain more than one node. | |
2142 | 1293 Value key = append(new Constant(new IntConstant(sw.low_key()))); |
1294 BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0)); | |
1295 BlockBegin* fsux = block_at(bci() + sw.default_offset()); | |
0 | 1296 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); |
1819 | 1297 ValueStack* state_before = is_bb ? copy_state_before() : NULL; |
0 | 1298 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); |
1299 } else { | |
1300 // collect successors | |
1301 BlockList* sux = new BlockList(l + 1, NULL); | |
1302 int i; | |
1303 bool has_bb = false; | |
1304 for (i = 0; i < l; i++) { | |
2142 | 1305 sux->at_put(i, block_at(bci() + sw.dest_offset_at(i))); |
1306 if (sw.dest_offset_at(i) < 0) has_bb = true; | |
0 | 1307 } |
1308 // add default successor | |
5925
4fabc16dc5bf
6910464: Lookupswitch and Tableswitch default branches not recognized as safepoints
roland
parents:
4943
diff
changeset
|
1309 if (sw.default_offset() < 0) has_bb = true; |
2142 | 1310 sux->at_put(i, block_at(bci() + sw.default_offset())); |
1819 | 1311 ValueStack* state_before = has_bb ? copy_state_before() : NULL; |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1312 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
|
1313 #ifdef ASSERT |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1314 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
|
1315 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
|
1316 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
|
1317 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
|
1318 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1319 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1320 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1321 #endif |
0 | 1322 } |
1323 } | |
1324 | |
1325 | |
1326 void GraphBuilder::lookup_switch() { | |
2142 | 1327 Bytecode_lookupswitch sw(stream()); |
1328 const int l = sw.number_of_pairs(); | |
0 | 1329 if (CanonicalizeNodes && l == 1) { |
1330 // total of 2 successors => use If instead of switch | |
1331 // Note: This code should go into the canonicalizer as soon as it can | |
1332 // can handle canonicalized forms that contain more than one node. | |
1333 // simplify to If | |
2142 | 1334 LookupswitchPair pair = sw.pair_at(0); |
1335 Value key = append(new Constant(new IntConstant(pair.match()))); | |
1336 BlockBegin* tsux = block_at(bci() + pair.offset()); | |
1337 BlockBegin* fsux = block_at(bci() + sw.default_offset()); | |
0 | 1338 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); |
1819 | 1339 ValueStack* state_before = is_bb ? copy_state_before() : NULL; |
0 | 1340 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); |
1341 } else { | |
1342 // collect successors & keys | |
1343 BlockList* sux = new BlockList(l + 1, NULL); | |
1344 intArray* keys = new intArray(l, 0); | |
1345 int i; | |
1346 bool has_bb = false; | |
1347 for (i = 0; i < l; i++) { | |
2142 | 1348 LookupswitchPair pair = sw.pair_at(i); |
1349 if (pair.offset() < 0) has_bb = true; | |
1350 sux->at_put(i, block_at(bci() + pair.offset())); | |
1351 keys->at_put(i, pair.match()); | |
0 | 1352 } |
1353 // add default successor | |
5925
4fabc16dc5bf
6910464: Lookupswitch and Tableswitch default branches not recognized as safepoints
roland
parents:
4943
diff
changeset
|
1354 if (sw.default_offset() < 0) has_bb = true; |
2142 | 1355 sux->at_put(i, block_at(bci() + sw.default_offset())); |
1819 | 1356 ValueStack* state_before = has_bb ? copy_state_before() : NULL; |
4943
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1357 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
|
1358 #ifdef ASSERT |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1359 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
|
1360 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
|
1361 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
|
1362 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
|
1363 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1364 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1365 } |
80107dc493db
7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
roland
parents:
4871
diff
changeset
|
1366 #endif |
0 | 1367 } |
1368 } | |
1369 | |
1370 void GraphBuilder::call_register_finalizer() { | |
1371 // If the receiver requires finalization then emit code to perform | |
1372 // the registration on return. | |
1373 | |
1374 // Gather some type information about the receiver | |
1819 | 1375 Value receiver = state()->local_at(0); |
0 | 1376 assert(receiver != NULL, "must have a receiver"); |
1377 ciType* declared_type = receiver->declared_type(); | |
1378 ciType* exact_type = receiver->exact_type(); | |
1379 if (exact_type == NULL && | |
1380 receiver->as_Local() && | |
1381 receiver->as_Local()->java_index() == 0) { | |
1382 ciInstanceKlass* ik = compilation()->method()->holder(); | |
1383 if (ik->is_final()) { | |
1384 exact_type = ik; | |
1385 } else if (UseCHA && !(ik->has_subklass() || ik->is_interface())) { | |
1386 // test class is leaf class | |
1387 compilation()->dependency_recorder()->assert_leaf_type(ik); | |
1388 exact_type = ik; | |
1389 } else { | |
1390 declared_type = ik; | |
1391 } | |
1392 } | |
1393 | |
1394 // see if we know statically that registration isn't required | |
1395 bool needs_check = true; | |
1396 if (exact_type != NULL) { | |
1397 needs_check = exact_type->as_instance_klass()->has_finalizer(); | |
1398 } else if (declared_type != NULL) { | |
1399 ciInstanceKlass* ik = declared_type->as_instance_klass(); | |
1400 if (!Dependencies::has_finalizable_subclass(ik)) { | |
1401 compilation()->dependency_recorder()->assert_has_no_finalizable_subclasses(ik); | |
1402 needs_check = false; | |
1403 } | |
1404 } | |
1405 | |
1406 if (needs_check) { | |
1407 // Perform the registration of finalizable objects. | |
1819 | 1408 ValueStack* state_before = copy_state_for_exception(); |
0 | 1409 load_local(objectType, 0); |
1410 append_split(new Intrinsic(voidType, vmIntrinsics::_Object_init, | |
1411 state()->pop_arguments(1), | |
1819 | 1412 true, state_before, true)); |
0 | 1413 } |
1414 } | |
1415 | |
1416 | |
1417 void GraphBuilder::method_return(Value x) { | |
1418 if (RegisterFinalizersAtInit && | |
1419 method()->intrinsic_id() == vmIntrinsics::_Object_init) { | |
1420 call_register_finalizer(); | |
1421 } | |
1422 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1423 bool need_mem_bar = false; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1424 if (method()->name() == ciSymbol::object_initializer_name() && |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1425 scope()->wrote_final()) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1426 need_mem_bar = true; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1427 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1428 |
0 | 1429 // Check to see whether we are inlining. If so, Return |
1430 // instructions become Gotos to the continuation point. | |
1431 if (continuation() != NULL) { | |
1432 assert(!method()->is_synchronized() || InlineSynchronizedMethods, "can not inline synchronized methods yet"); | |
1433 | |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1434 if (compilation()->env()->dtrace_method_probes()) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1435 // Report exit from inline methods |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1436 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
1437 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
|
1438 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
|
1439 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
1440 |
0 | 1441 // If the inlined method is synchronized, the monitor must be |
1442 // released before we jump to the continuation block. | |
1443 if (method()->is_synchronized()) { | |
1819 | 1444 assert(state()->locks_size() == 1, "receiver must be locked here"); |
1445 monitorexit(state()->lock_at(0), SynchronizationEntryBCI); | |
0 | 1446 } |
1447 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1448 if (need_mem_bar) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1449 append(new MemBar(lir_membar_storestore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1450 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1451 |
1819 | 1452 // State at end of inlined method is the state of the caller |
1453 // without the method parameters on stack, including the | |
1454 // return value, if any, of the inlined method on operand stack. | |
1455 set_state(state()->caller_state()->copy_for_parsing()); | |
0 | 1456 if (x != NULL) { |
1457 state()->push(x->type(), x); | |
1458 } | |
1459 Goto* goto_callee = new Goto(continuation(), false); | |
1460 | |
1461 // See whether this is the first return; if so, store off some | |
1462 // of the state for later examination | |
1463 if (num_returns() == 0) { | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1464 set_inline_cleanup_info(); |
0 | 1465 } |
1466 | |
1467 // The current bci() is in the wrong scope, so use the bci() of | |
1468 // the continuation point. | |
1469 append_with_bci(goto_callee, scope_data()->continuation()->bci()); | |
1470 incr_num_returns(); | |
1471 return; | |
1472 } | |
1473 | |
1474 state()->truncate_stack(0); | |
1475 if (method()->is_synchronized()) { | |
1476 // perform the unlocking before exiting the method | |
1477 Value receiver; | |
1478 if (!method()->is_static()) { | |
1479 receiver = _initial_state->local_at(0); | |
1480 } else { | |
1481 receiver = append(new Constant(new ClassConstant(method()->holder()))); | |
1482 } | |
1483 append_split(new MonitorExit(receiver, state()->unlock())); | |
1484 } | |
1485 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1486 if (need_mem_bar) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1487 append(new MemBar(lir_membar_storestore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1488 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1489 |
0 | 1490 append(new Return(x)); |
1491 } | |
1492 | |
1493 | |
1494 void GraphBuilder::access_field(Bytecodes::Code code) { | |
1495 bool will_link; | |
1496 ciField* field = stream()->get_field(will_link); | |
1497 ciInstanceKlass* holder = field->holder(); | |
1498 BasicType field_type = field->type()->basic_type(); | |
1499 ValueType* type = as_ValueType(field_type); | |
1500 // 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
|
1501 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
|
1502 !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
|
1503 PatchALot; |
0 | 1504 |
1819 | 1505 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
|
1506 if (!holder->is_initialized() || needs_patching) { |
0 | 1507 // save state before instruction for debug info when |
1508 // deoptimization happens during patching | |
1819 | 1509 state_before = copy_state_before(); |
0 | 1510 } |
1511 | |
1512 Value obj = NULL; | |
1513 if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) { | |
1819 | 1514 if (state_before != NULL) { |
0 | 1515 // build a patching constant |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2352
diff
changeset
|
1516 obj = new Constant(new InstanceConstant(holder->java_mirror()), state_before); |
0 | 1517 } else { |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2352
diff
changeset
|
1518 obj = new Constant(new InstanceConstant(holder->java_mirror())); |
0 | 1519 } |
1520 } | |
1521 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1522 if (field->is_final() && (code == Bytecodes::_putfield)) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1523 scope()->set_wrote_final(); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4943
diff
changeset
|
1524 } |
0 | 1525 |
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
|
1526 const int offset = !needs_patching ? field->offset() : -1; |
0 | 1527 switch (code) { |
1528 case Bytecodes::_getstatic: { | |
1529 // check for compile-time constants, i.e., initialized static final fields | |
1530 Instruction* constant = NULL; | |
1531 if (field->is_constant() && !PatchALot) { | |
1532 ciConstant field_val = field->constant_value(); | |
1533 BasicType field_type = field_val.basic_type(); | |
1534 switch (field_type) { | |
1535 case T_ARRAY: | |
1536 case T_OBJECT: | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
1537 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
|
1538 constant = new Constant(as_ValueType(field_val)); |
0 | 1539 } |
1540 break; | |
1541 | |
1542 default: | |
1543 constant = new Constant(as_ValueType(field_val)); | |
1544 } | |
1545 } | |
1546 if (constant != NULL) { | |
1547 push(type, append(constant)); | |
1548 } else { | |
1819 | 1549 if (state_before == NULL) { |
1550 state_before = copy_state_for_exception(); | |
1551 } | |
0 | 1552 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
|
1553 state_before, needs_patching))); |
0 | 1554 } |
1555 break; | |
1556 } | |
1557 case Bytecodes::_putstatic: | |
1558 { Value val = pop(type); | |
1819 | 1559 if (state_before == NULL) { |
1560 state_before = copy_state_for_exception(); | |
1561 } | |
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
|
1562 append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); |
0 | 1563 } |
1564 break; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1565 case Bytecodes::_getfield: { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1566 // 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
|
1567 Instruction* constant = NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1568 obj = apop(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1569 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
|
1570 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
|
1571 ciObject* const_oop = obj_type->constant_value(); |
6267
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1572 if (!const_oop->is_null_object()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1573 if (field->is_constant()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1574 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
|
1575 BasicType field_type = field_val.basic_type(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1576 switch (field_type) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1577 case T_ARRAY: |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1578 case T_OBJECT: |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1579 if (field_val.as_object()->should_be_constant()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1580 constant = new Constant(as_ValueType(field_val)); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1581 } |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1582 break; |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1583 default: |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1584 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
|
1585 } |
6267
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1586 } else { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1587 // 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
|
1588 if (const_oop->is_call_site()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1589 ciCallSite* call_site = const_oop->as_call_site(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1590 if (field->is_call_site_target()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1591 ciMethodHandle* target = call_site->get_target(); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1592 if (target != NULL) { // just in case |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1593 ciConstant field_val(T_OBJECT, target); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1594 constant = new Constant(as_ValueType(field_val)); |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1595 // Add a dependence for invalidation of the optimization. |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1596 if (!call_site->is_constant_call_site()) { |
977007096840
7187290: nightly failures after JSR 292 lazy method handle update
twisti
parents:
6266
diff
changeset
|
1597 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
|
1598 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1599 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1600 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1601 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1602 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1603 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1604 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1605 if (constant != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1606 push(type, append(constant)); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1607 } else { |
1819 | 1608 if (state_before == NULL) { |
1609 state_before = copy_state_for_exception(); | |
1610 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1611 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
|
1612 Value replacement = !needs_patching ? _memory->load(load) : load; |
0 | 1613 if (replacement != load) { |
1819 | 1614 assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); |
0 | 1615 push(type, replacement); |
1616 } else { | |
1617 push(type, append(load)); | |
1618 } | |
1619 } | |
1620 break; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1621 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1622 case Bytecodes::_putfield: { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1623 Value val = pop(type); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1624 obj = apop(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1625 if (state_before == NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1626 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
|
1627 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1628 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
|
1629 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
|
1630 if (store != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1631 append(store); |
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 break; |
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 default: |
0 | 1636 ShouldNotReachHere(); |
1637 break; | |
1638 } | |
1639 } | |
1640 | |
1641 | |
1642 Dependencies* GraphBuilder::dependency_recorder() const { | |
1643 assert(DeoptC1, "need debug information"); | |
1644 return compilation()->dependency_recorder(); | |
1645 } | |
1646 | |
1647 | |
1648 void GraphBuilder::invoke(Bytecodes::Code code) { | |
1649 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
|
1650 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
|
1651 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
|
1652 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
|
1653 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
|
1654 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
|
1655 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1656 // FIXME bail out for now |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1657 if (Bytecodes::has_optional_appendix(bc_raw) && !will_link) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1658 BAILOUT("unlinked call site (FIXME needs patching or recompile support)"); |
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 |
0 | 1661 // we have to make sure the argument size (incl. the receiver) |
1662 // is correct for compilation (the call would fail later during | |
1663 // 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
|
1664 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1665 // 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
|
1666 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
|
1667 const bool allow_static = |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1668 is_invokestatic || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1669 bc_raw == Bytecodes::_invokehandle || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1670 bc_raw == Bytecodes::_invokedynamic; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1671 if (target->is_loaded()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1672 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
|
1673 (!target->is_static() && is_invokestatic)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1674 BAILOUT("will cause link error"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1675 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1676 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1677 } |
0 | 1678 ciInstanceKlass* klass = target->holder(); |
1679 | |
1680 // check if CHA possible: if so, change the code to invoke_special | |
1681 ciInstanceKlass* calling_klass = method()->holder(); | |
1682 ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); | |
1683 ciInstanceKlass* actual_recv = callee_holder; | |
1684 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1685 // 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
|
1686 // 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
|
1687 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
|
1688 switch (bc_raw) { |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1689 case Bytecodes::_invokevirtual: |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1690 code = Bytecodes::_invokespecial; |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1691 break; |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1692 case Bytecodes::_invokehandle: |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1693 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
|
1694 break; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1695 } |
0 | 1696 } |
1697 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1698 // Push appendix argument (MethodType, CallSite, etc.), if one. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1699 if (stream()->has_appendix()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1700 ciObject* appendix = stream()->get_appendix(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1701 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
|
1702 apush(arg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1703 } |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1704 |
0 | 1705 // NEEDS_CLEANUP |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1706 // I've added the target->is_loaded() test below but I don't really understand |
0 | 1707 // how klass->is_loaded() can be true and yet target->is_loaded() is false. |
1708 // this happened while running the JCK invokevirtual tests under doit. TKR | |
1709 ciMethod* cha_monomorphic_target = NULL; | |
1710 ciMethod* exact_target = NULL; | |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1711 Value better_receiver = NULL; |
1295 | 1712 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
|
1713 !(// %%% 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
|
1714 target->is_method_handle_intrinsic() || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1715 target->is_compiled_lambda_form())) { |
0 | 1716 Value receiver = NULL; |
1717 ciInstanceKlass* receiver_klass = NULL; | |
1718 bool type_is_exact = false; | |
1719 // try to find a precise receiver type | |
1720 if (will_link && !target->is_static()) { | |
1721 int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); | |
1722 receiver = state()->stack_at(index); | |
1723 ciType* type = receiver->exact_type(); | |
1724 if (type != NULL && type->is_loaded() && | |
1725 type->is_instance_klass() && !type->as_instance_klass()->is_interface()) { | |
1726 receiver_klass = (ciInstanceKlass*) type; | |
1727 type_is_exact = true; | |
1728 } | |
1729 if (type == NULL) { | |
1730 type = receiver->declared_type(); | |
1731 if (type != NULL && type->is_loaded() && | |
1732 type->is_instance_klass() && !type->as_instance_klass()->is_interface()) { | |
1733 receiver_klass = (ciInstanceKlass*) type; | |
1734 if (receiver_klass->is_leaf_type() && !receiver_klass->is_final()) { | |
1735 // Insert a dependency on this type since | |
1736 // find_monomorphic_target may assume it's already done. | |
1737 dependency_recorder()->assert_leaf_type(receiver_klass); | |
1738 type_is_exact = true; | |
1739 } | |
1740 } | |
1741 } | |
1742 } | |
1743 if (receiver_klass != NULL && type_is_exact && | |
1744 receiver_klass->is_loaded() && code != Bytecodes::_invokespecial) { | |
1745 // If we have the exact receiver type we can bind directly to | |
1746 // the method to call. | |
1747 exact_target = target->resolve_invoke(calling_klass, receiver_klass); | |
1748 if (exact_target != NULL) { | |
1749 target = exact_target; | |
1750 code = Bytecodes::_invokespecial; | |
1751 } | |
1752 } | |
1753 if (receiver_klass != NULL && | |
1754 receiver_klass->is_subtype_of(actual_recv) && | |
1755 actual_recv->is_initialized()) { | |
1756 actual_recv = receiver_klass; | |
1757 } | |
1758 | |
1759 if ((code == Bytecodes::_invokevirtual && callee_holder->is_initialized()) || | |
1760 (code == Bytecodes::_invokeinterface && callee_holder->is_initialized() && !actual_recv->is_interface())) { | |
1761 // Use CHA on the receiver to select a more precise method. | |
1762 cha_monomorphic_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); | |
1763 } else if (code == Bytecodes::_invokeinterface && callee_holder->is_loaded() && receiver != NULL) { | |
1764 // if there is only one implementor of this interface then we | |
1765 // may be able bind this invoke directly to the implementing | |
1766 // klass but we need both a dependence on the single interface | |
1767 // and on the method we bind to. Additionally since all we know | |
1768 // about the receiver type is the it's supposed to implement the | |
1769 // interface we have to insert a check that it's the class we | |
1770 // expect. Interface types are not checked by the verifier so | |
1771 // they are roughly equivalent to Object. | |
1772 ciInstanceKlass* singleton = NULL; | |
1773 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
|
1774 singleton = target->holder()->implementor(); |
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
5926
diff
changeset
|
1775 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
|
1776 "just checking"); |
4871
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1777 |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1778 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
|
1779 ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1780 // 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
|
1781 // 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
|
1782 // 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
|
1783 // 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
|
1784 // 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
|
1785 // no point in inlining. |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1786 if (!holder->is_loaded() || decl_interface->nof_implementors() != 1) { |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1787 singleton = NULL; |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1788 } |
0 | 1789 } |
1790 if (singleton) { | |
1791 cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); | |
1792 if (cha_monomorphic_target != NULL) { | |
1793 // If CHA is able to bind this invoke then update the class | |
1794 // to match that class, otherwise klass will refer to the | |
1795 // interface. | |
1796 klass = cha_monomorphic_target->holder(); | |
1797 actual_recv = target->holder(); | |
1798 | |
1799 // insert a check it's really the expected class. | |
1819 | 1800 CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); |
0 | 1801 c->set_incompatible_class_change_check(); |
1802 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
|
1803 // 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
|
1804 // more accurate type info in the inlinee |
f067b4e0e04b
7090976: Eclipse/CDT causes a JVM crash while indexing C++ code
roland
parents:
4870
diff
changeset
|
1805 better_receiver = append_split(c); |
0 | 1806 } |
1807 } | |
1808 } | |
1809 } | |
1810 | |
1811 if (cha_monomorphic_target != NULL) { | |
1812 if (cha_monomorphic_target->is_abstract()) { | |
1813 // Do not optimize for abstract methods | |
1814 cha_monomorphic_target = NULL; | |
1815 } | |
1816 } | |
1817 | |
1818 if (cha_monomorphic_target != NULL) { | |
1819 if (!(target->is_final_method())) { | |
1820 // If we inlined because CHA revealed only a single target method, | |
1821 // then we are dependent on that target method not getting overridden | |
1822 // by dynamic class loading. Be sure to test the "static" receiver | |
1823 // dest_method here, as opposed to the actual receiver, which may | |
1824 // falsely lead us to believe that the receiver is final or private. | |
1825 dependency_recorder()->assert_unique_concrete_method(actual_recv, cha_monomorphic_target); | |
1826 } | |
1827 code = Bytecodes::_invokespecial; | |
1828 } | |
1829 // check if we could do inlining | |
1830 if (!PatchALot && Inline && klass->is_loaded() && | |
1831 (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) | |
1832 && target->will_link(klass, callee_holder, code)) { | |
1833 // callee is known => check if we have static binding | |
1834 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
|
1835 if (code == Bytecodes::_invokestatic || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1836 code == Bytecodes::_invokespecial || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1837 code == Bytecodes::_invokevirtual && target->is_final_method() || |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1838 code == Bytecodes::_invokedynamic) { |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1839 ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1840 bool success = false; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1841 if (target->is_method_handle_intrinsic()) { |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1842 // method handle invokes |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
1843 success = 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
|
1844 } else { |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1845 // static binding => check if callee is ok |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1846 success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver); |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1847 } |
0 | 1848 CHECK_BAILOUT(); |
1849 | |
1850 clear_inline_bailout(); | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
1851 if (success) { |
0 | 1852 // Register dependence if JVMTI has either breakpoint |
1853 // setting or hotswapping of methods capabilities since they may | |
1854 // 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
|
1855 if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) { |
0 | 1856 dependency_recorder()->assert_evol_method(inline_target); |
1857 } | |
1858 return; | |
1859 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1860 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1861 print_inlining(target, "no static binding", /*success*/ false); |
0 | 1862 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1863 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1864 print_inlining(target, "not inlineable", /*success*/ false); |
0 | 1865 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1866 |
0 | 1867 // If we attempted an inline which did not succeed because of a |
1868 // bailout during construction of the callee graph, the entire | |
1869 // compilation has to be aborted. This is fairly rare and currently | |
1870 // seems to only occur for jasm-generated classes which contain | |
1871 // jsr/ret pairs which are not associated with finally clauses and | |
1872 // do not have exception handlers in the containing method, and are | |
1873 // therefore not caught early enough to abort the inlining without | |
1874 // corrupting the graph. (We currently bail out with a non-empty | |
1875 // stack at a ret in these situations.) | |
1876 CHECK_BAILOUT(); | |
1877 | |
1878 // inlining not successful => standard invoke | |
1295 | 1879 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
|
1880 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
|
1881 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
|
1882 |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1883 // 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
|
1884 const bool has_receiver = |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1885 code == Bytecodes::_invokespecial || |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1886 code == Bytecodes::_invokevirtual || |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
1887 code == Bytecodes::_invokeinterface; |
0 | 1888 Values* args = state()->pop_arguments(target->arg_size_no_receiver()); |
1295 | 1889 Value recv = has_receiver ? apop() : NULL; |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
1890 int vtable_index = Method::invalid_vtable_index; |
0 | 1891 |
1892 #ifdef SPARC | |
1893 // Currently only supported on Sparc. | |
1894 // The UseInlineCaches only controls dispatch to invokevirtuals for | |
1895 // loaded classes which we weren't able to statically bind. | |
1896 if (!UseInlineCaches && is_loaded && code == Bytecodes::_invokevirtual | |
1897 && !target->can_be_statically_bound()) { | |
1898 // Find a vtable index if one is available | |
1899 vtable_index = target->resolve_vtable_index(calling_klass, callee_holder); | |
1900 } | |
1901 #endif | |
1902 | |
1903 if (recv != NULL && | |
1904 (code == Bytecodes::_invokespecial || | |
1783 | 1905 !is_loaded || target->is_final())) { |
0 | 1906 // invokespecial always needs a NULL check. invokevirtual where |
1907 // the target is final or where it's not known that whether the | |
1908 // target is final requires a NULL check. Otherwise normal | |
1909 // invokevirtual will perform the null check during the lookup | |
1910 // logic or the unverified entry point. Profiling of calls | |
1911 // requires that the null check is performed in all cases. | |
1912 null_check(recv); | |
1913 } | |
1914 | |
1783 | 1915 if (is_profiling()) { |
1916 if (recv != NULL && profile_calls()) { | |
1917 null_check(recv); | |
0 | 1918 } |
1783 | 1919 // Note that we'd collect profile data in this method if we wanted it. |
1920 compilation()->set_would_profile(true); | |
1921 | |
1922 if (profile_calls()) { | |
1923 assert(cha_monomorphic_target == NULL || exact_target == NULL, "both can not be set"); | |
1924 ciKlass* target_klass = NULL; | |
1925 if (cha_monomorphic_target != NULL) { | |
1926 target_klass = cha_monomorphic_target->holder(); | |
1927 } else if (exact_target != NULL) { | |
1928 target_klass = exact_target->holder(); | |
1929 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
1930 profile_call(target, recv, target_klass); |
1783 | 1931 } |
0 | 1932 } |
1933 | |
1295 | 1934 Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before); |
0 | 1935 // push result |
1936 append_split(result); | |
1937 | |
1938 if (result_type != voidType) { | |
1939 if (method()->is_strict()) { | |
1940 push(result_type, round_fp(result)); | |
1941 } else { | |
1942 push(result_type, result); | |
1943 } | |
1944 } | |
1945 } | |
1946 | |
1947 | |
1948 void GraphBuilder::new_instance(int klass_index) { | |
1819 | 1949 ValueStack* state_before = copy_state_exhandling(); |
0 | 1950 bool will_link; |
1951 ciKlass* klass = stream()->get_klass(will_link); | |
1952 assert(klass->is_instance_klass(), "must be an instance klass"); | |
1819 | 1953 NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before); |
0 | 1954 _memory->new_instance(new_instance); |
1955 apush(append_split(new_instance)); | |
1956 } | |
1957 | |
1958 | |
1959 void GraphBuilder::new_type_array() { | |
1819 | 1960 ValueStack* state_before = copy_state_exhandling(); |
1961 apush(append_split(new NewTypeArray(ipop(), (BasicType)stream()->get_index(), state_before))); | |
0 | 1962 } |
1963 | |
1964 | |
1965 void GraphBuilder::new_object_array() { | |
1966 bool will_link; | |
1967 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 1968 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 1969 NewArray* n = new NewObjectArray(klass, ipop(), state_before); |
1970 apush(append_split(n)); | |
1971 } | |
1972 | |
1973 | |
1974 bool GraphBuilder::direct_compare(ciKlass* k) { | |
1975 if (k->is_loaded() && k->is_instance_klass() && !UseSlowPath) { | |
1976 ciInstanceKlass* ik = k->as_instance_klass(); | |
1977 if (ik->is_final()) { | |
1978 return true; | |
1979 } else { | |
1980 if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) { | |
1981 // test class is leaf class | |
1982 dependency_recorder()->assert_leaf_type(ik); | |
1983 return true; | |
1984 } | |
1985 } | |
1986 } | |
1987 return false; | |
1988 } | |
1989 | |
1990 | |
1991 void GraphBuilder::check_cast(int klass_index) { | |
1992 bool will_link; | |
1993 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 1994 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_for_exception(); |
0 | 1995 CheckCast* c = new CheckCast(klass, apop(), state_before); |
1996 apush(append_split(c)); | |
1997 c->set_direct_compare(direct_compare(klass)); | |
1783 | 1998 |
1999 if (is_profiling()) { | |
2000 // Note that we'd collect profile data in this method if we wanted it. | |
2001 compilation()->set_would_profile(true); | |
2002 | |
2003 if (profile_checkcasts()) { | |
2004 c->set_profiled_method(method()); | |
2005 c->set_profiled_bci(bci()); | |
2006 c->set_should_profile(true); | |
2007 } | |
0 | 2008 } |
2009 } | |
2010 | |
2011 | |
2012 void GraphBuilder::instance_of(int klass_index) { | |
2013 bool will_link; | |
2014 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2015 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 2016 InstanceOf* i = new InstanceOf(klass, apop(), state_before); |
2017 ipush(append_split(i)); | |
2018 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
|
2019 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2020 if (is_profiling()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2021 // 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
|
2022 compilation()->set_would_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2023 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2024 if (profile_checkcasts()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2025 i->set_profiled_method(method()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2026 i->set_profiled_bci(bci()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2027 i->set_should_profile(true); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2028 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1783
diff
changeset
|
2029 } |
0 | 2030 } |
2031 | |
2032 | |
2033 void GraphBuilder::monitorenter(Value x, int bci) { | |
2034 // save state before locking in case of deoptimization after a NullPointerException | |
1819 | 2035 ValueStack* state_before = copy_state_for_exception_with_bci(bci); |
2036 append_with_bci(new MonitorEnter(x, state()->lock(x), state_before), bci); | |
0 | 2037 kill_all(); |
2038 } | |
2039 | |
2040 | |
2041 void GraphBuilder::monitorexit(Value x, int bci) { | |
2042 append_with_bci(new MonitorExit(x, state()->unlock()), bci); | |
2043 kill_all(); | |
2044 } | |
2045 | |
2046 | |
2047 void GraphBuilder::new_multi_array(int dimensions) { | |
2048 bool will_link; | |
2049 ciKlass* klass = stream()->get_klass(will_link); | |
1819 | 2050 ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling(); |
0 | 2051 |
2052 Values* dims = new Values(dimensions, NULL); | |
2053 // fill in all dimensions | |
2054 int i = dimensions; | |
2055 while (i-- > 0) dims->at_put(i, ipop()); | |
2056 // create array | |
2057 NewArray* n = new NewMultiArray(klass, dims, state_before); | |
2058 apush(append_split(n)); | |
2059 } | |
2060 | |
2061 | |
2062 void GraphBuilder::throw_op(int bci) { | |
2063 // We require that the debug info for a Throw be the "state before" | |
2064 // the Throw (i.e., exception oop is still on TOS) | |
1819 | 2065 ValueStack* state_before = copy_state_before_with_bci(bci); |
0 | 2066 Throw* t = new Throw(apop(), state_before); |
1819 | 2067 // operand stack not needed after a throw |
2068 state()->truncate_stack(0); | |
0 | 2069 append_with_bci(t, bci); |
2070 } | |
2071 | |
2072 | |
2073 Value GraphBuilder::round_fp(Value fp_value) { | |
2074 // no rounding needed if SSE2 is used | |
2075 if (RoundFPResults && UseSSE < 2) { | |
2076 // Must currently insert rounding node for doubleword values that | |
2077 // are results of expressions (i.e., not loads from memory or | |
2078 // constants) | |
2079 if (fp_value->type()->tag() == doubleTag && | |
2080 fp_value->as_Constant() == NULL && | |
2081 fp_value->as_Local() == NULL && // method parameters need no rounding | |
2082 fp_value->as_RoundFP() == NULL) { | |
2083 return append(new RoundFP(fp_value)); | |
2084 } | |
2085 } | |
2086 return fp_value; | |
2087 } | |
2088 | |
2089 | |
2090 Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) { | |
1783 | 2091 Canonicalizer canon(compilation(), instr, bci); |
0 | 2092 Instruction* i1 = canon.canonical(); |
1819 | 2093 if (i1->is_linked() || !i1->can_be_linked()) { |
0 | 2094 // Canonicalizer returned an instruction which was already |
2095 // appended so simply return it. | |
2096 return i1; | |
1819 | 2097 } |
2098 | |
2099 if (UseLocalValueNumbering) { | |
0 | 2100 // Lookup the instruction in the ValueMap and add it to the map if |
2101 // it's not found. | |
2102 Instruction* i2 = vmap()->find_insert(i1); | |
2103 if (i2 != i1) { | |
2104 // found an entry in the value map, so just return it. | |
1819 | 2105 assert(i2->is_linked(), "should already be linked"); |
0 | 2106 return i2; |
2107 } | |
459 | 2108 ValueNumberingEffects vne(vmap()); |
2109 i1->visit(&vne); | |
0 | 2110 } |
2111 | |
1819 | 2112 // i1 was not eliminated => append it |
2113 assert(i1->next() == NULL, "shouldn't already be linked"); | |
2114 _last = _last->set_next(i1, canon.bci()); | |
2115 | |
2116 if (++_instruction_count >= InstructionCountCutoff && !bailed_out()) { | |
2117 // set the bailout state but complete normal processing. We | |
2118 // might do a little more work before noticing the bailout so we | |
2119 // want processing to continue normally until it's noticed. | |
2120 bailout("Method and/or inlining is too large"); | |
2121 } | |
0 | 2122 |
2123 #ifndef PRODUCT | |
1819 | 2124 if (PrintIRDuringConstruction) { |
2125 InstructionPrinter ip; | |
2126 ip.print_line(i1); | |
2127 if (Verbose) { | |
2128 state()->print(); | |
2129 } | |
2130 } | |
2131 #endif | |
2132 | |
2133 // save state after modification of operand stack for StateSplit instructions | |
2134 StateSplit* s = i1->as_StateSplit(); | |
2135 if (s != NULL) { | |
2136 if (EliminateFieldAccess) { | |
2137 Intrinsic* intrinsic = s->as_Intrinsic(); | |
2138 if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) { | |
2139 _memory->kill(); | |
0 | 2140 } |
2141 } | |
1819 | 2142 s->set_state(state()->copy(ValueStack::StateAfter, canon.bci())); |
2143 } | |
2144 | |
2145 // set up exception handlers for this instruction if necessary | |
2146 if (i1->can_trap()) { | |
2147 i1->set_exception_handlers(handle_exception(i1)); | |
2148 assert(i1->exception_state() != NULL || !i1->needs_exception_state() || bailed_out(), "handle_exception must set exception state"); | |
0 | 2149 } |
2150 return i1; | |
2151 } | |
2152 | |
2153 | |
2154 Instruction* GraphBuilder::append(Instruction* instr) { | |
2155 assert(instr->as_StateSplit() == NULL || instr->as_BlockEnd() != NULL, "wrong append used"); | |
2156 return append_with_bci(instr, bci()); | |
2157 } | |
2158 | |
2159 | |
2160 Instruction* GraphBuilder::append_split(StateSplit* instr) { | |
2161 return append_with_bci(instr, bci()); | |
2162 } | |
2163 | |
2164 | |
2165 void GraphBuilder::null_check(Value value) { | |
2166 if (value->as_NewArray() != NULL || value->as_NewInstance() != NULL) { | |
2167 return; | |
2168 } else { | |
2169 Constant* con = value->as_Constant(); | |
2170 if (con) { | |
2171 ObjectType* c = con->type()->as_ObjectType(); | |
2172 if (c && c->is_loaded()) { | |
2173 ObjectConstant* oc = c->as_ObjectConstant(); | |
2174 if (!oc || !oc->value()->is_null_object()) { | |
2175 return; | |
2176 } | |
2177 } | |
2178 } | |
2179 } | |
1819 | 2180 append(new NullCheck(value, copy_state_for_exception())); |
0 | 2181 } |
2182 | |
2183 | |
2184 | |
1819 | 2185 XHandlers* GraphBuilder::handle_exception(Instruction* instruction) { |
2186 if (!has_handler() && (!instruction->needs_exception_state() || instruction->exception_state() != NULL)) { | |
2187 assert(instruction->exception_state() == NULL | |
2188 || instruction->exception_state()->kind() == ValueStack::EmptyExceptionState | |
2189 || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->jvmti_can_access_local_variables()), | |
2190 "exception_state should be of exception kind"); | |
0 | 2191 return new XHandlers(); |
2192 } | |
2193 | |
2194 XHandlers* exception_handlers = new XHandlers(); | |
2195 ScopeData* cur_scope_data = scope_data(); | |
1819 | 2196 ValueStack* cur_state = instruction->state_before(); |
2197 ValueStack* prev_state = NULL; | |
0 | 2198 int scope_count = 0; |
2199 | |
1819 | 2200 assert(cur_state != NULL, "state_before must be set"); |
0 | 2201 do { |
1819 | 2202 int cur_bci = cur_state->bci(); |
2203 assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match"); | |
0 | 2204 assert(cur_bci == SynchronizationEntryBCI || cur_bci == cur_scope_data->stream()->cur_bci(), "invalid bci"); |
2205 | |
2206 // join with all potential exception handlers | |
2207 XHandlers* list = cur_scope_data->xhandlers(); | |
2208 const int n = list->length(); | |
2209 for (int i = 0; i < n; i++) { | |
2210 XHandler* h = list->handler_at(i); | |
2211 if (h->covers(cur_bci)) { | |
2212 // h is a potential exception handler => join it | |
2213 compilation()->set_has_exception_handlers(true); | |
2214 | |
2215 BlockBegin* entry = h->entry_block(); | |
2216 if (entry == block()) { | |
2217 // It's acceptable for an exception handler to cover itself | |
2218 // but we don't handle that in the parser currently. It's | |
2219 // very rare so we bailout instead of trying to handle it. | |
2220 BAILOUT_("exception handler covers itself", exception_handlers); | |
2221 } | |
2222 assert(entry->bci() == h->handler_bci(), "must match"); | |
2223 assert(entry->bci() == -1 || entry == cur_scope_data->block_at(entry->bci()), "blocks must correspond"); | |
2224 | |
2225 // previously this was a BAILOUT, but this is not necessary | |
2226 // now because asynchronous exceptions are not handled this way. | |
1819 | 2227 assert(entry->state() == NULL || cur_state->total_locks_size() == entry->state()->total_locks_size(), "locks do not match"); |
0 | 2228 |
2229 // xhandler start with an empty expression stack | |
1819 | 2230 if (cur_state->stack_size() != 0) { |
2231 cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci()); | |
2232 } | |
2233 if (instruction->exception_state() == NULL) { | |
2234 instruction->set_exception_state(cur_state); | |
2235 } | |
0 | 2236 |
2237 // Note: Usually this join must work. However, very | |
2238 // complicated jsr-ret structures where we don't ret from | |
2239 // the subroutine can cause the objects on the monitor | |
2240 // stacks to not match because blocks can be parsed twice. | |
2241 // The only test case we've seen so far which exhibits this | |
2242 // problem is caught by the infinite recursion test in | |
2243 // GraphBuilder::jsr() if the join doesn't work. | |
1819 | 2244 if (!entry->try_merge(cur_state)) { |
0 | 2245 BAILOUT_("error while joining with exception handler, prob. due to complicated jsr/rets", exception_handlers); |
2246 } | |
2247 | |
2248 // add current state for correct handling of phi functions at begin of xhandler | |
1819 | 2249 int phi_operand = entry->add_exception_state(cur_state); |
0 | 2250 |
2251 // add entry to the list of xhandlers of this block | |
2252 _block->add_exception_handler(entry); | |
2253 | |
2254 // add back-edge from xhandler entry to this block | |
2255 if (!entry->is_predecessor(_block)) { | |
2256 entry->add_predecessor(_block); | |
2257 } | |
2258 | |
2259 // clone XHandler because phi_operand and scope_count can not be shared | |
2260 XHandler* new_xhandler = new XHandler(h); | |
2261 new_xhandler->set_phi_operand(phi_operand); | |
2262 new_xhandler->set_scope_count(scope_count); | |
2263 exception_handlers->append(new_xhandler); | |
2264 | |
2265 // fill in exception handler subgraph lazily | |
2266 assert(!entry->is_set(BlockBegin::was_visited_flag), "entry must not be visited yet"); | |
2267 cur_scope_data->add_to_work_list(entry); | |
2268 | |
2269 // stop when reaching catchall | |
2270 if (h->catch_type() == 0) { | |
2271 return exception_handlers; | |
2272 } | |
2273 } | |
2274 } | |
2275 | |
1819 | 2276 if (exception_handlers->length() == 0) { |
2277 // This scope and all callees do not handle exceptions, so the local | |
2278 // variables of this scope are not needed. However, the scope itself is | |
2279 // required for a correct exception stack trace -> clear out the locals. | |
2280 if (_compilation->env()->jvmti_can_access_local_variables()) { | |
2281 cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci()); | |
2282 } else { | |
2283 cur_state = cur_state->copy(ValueStack::EmptyExceptionState, cur_state->bci()); | |
2284 } | |
2285 if (prev_state != NULL) { | |
2286 prev_state->set_caller_state(cur_state); | |
2287 } | |
2288 if (instruction->exception_state() == NULL) { | |
2289 instruction->set_exception_state(cur_state); | |
2290 } | |
2291 } | |
2292 | |
0 | 2293 // Set up iteration for next time. |
2294 // If parsing a jsr, do not grab exception handlers from the | |
2295 // parent scopes for this method (already got them, and they | |
2296 // needed to be cloned) | |
1819 | 2297 |
2298 while (cur_scope_data->parsing_jsr()) { | |
2299 cur_scope_data = cur_scope_data->parent(); | |
0 | 2300 } |
1819 | 2301 |
2302 assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match"); | |
2303 assert(cur_state->locks_size() == 0 || cur_state->locks_size() == 1, "unlocking must be done in a catchall exception handler"); | |
2304 | |
2305 prev_state = cur_state; | |
2306 cur_state = cur_state->caller_state(); | |
2307 cur_scope_data = cur_scope_data->parent(); | |
2308 scope_count++; | |
0 | 2309 } while (cur_scope_data != NULL); |
2310 | |
2311 return exception_handlers; | |
2312 } | |
2313 | |
2314 | |
2315 // Helper class for simplifying Phis. | |
2316 class PhiSimplifier : public BlockClosure { | |
2317 private: | |
2318 bool _has_substitutions; | |
2319 Value simplify(Value v); | |
2320 | |
2321 public: | |
2322 PhiSimplifier(BlockBegin* start) : _has_substitutions(false) { | |
2323 start->iterate_preorder(this); | |
2324 if (_has_substitutions) { | |
2325 SubstitutionResolver sr(start); | |
2326 } | |
2327 } | |
2328 void block_do(BlockBegin* b); | |
2329 bool has_substitutions() const { return _has_substitutions; } | |
2330 }; | |
2331 | |
2332 | |
2333 Value PhiSimplifier::simplify(Value v) { | |
2334 Phi* phi = v->as_Phi(); | |
2335 | |
2336 if (phi == NULL) { | |
2337 // no phi function | |
2338 return v; | |
2339 } else if (v->has_subst()) { | |
2340 // already substituted; subst can be phi itself -> simplify | |
2341 return simplify(v->subst()); | |
2342 } else if (phi->is_set(Phi::cannot_simplify)) { | |
2343 // already tried to simplify phi before | |
2344 return phi; | |
2345 } else if (phi->is_set(Phi::visited)) { | |
2346 // break cycles in phi functions | |
2347 return phi; | |
2348 } else if (phi->type()->is_illegal()) { | |
2349 // illegal phi functions are ignored anyway | |
2350 return phi; | |
2351 | |
2352 } else { | |
2353 // mark phi function as processed to break cycles in phi functions | |
2354 phi->set(Phi::visited); | |
2355 | |
2356 // simplify x = [y, x] and x = [y, y] to y | |
2357 Value subst = NULL; | |
2358 int opd_count = phi->operand_count(); | |
2359 for (int i = 0; i < opd_count; i++) { | |
2360 Value opd = phi->operand_at(i); | |
2361 assert(opd != NULL, "Operand must exist!"); | |
2362 | |
2363 if (opd->type()->is_illegal()) { | |
2364 // if one operand is illegal, the entire phi function is illegal | |
2365 phi->make_illegal(); | |
2366 phi->clear(Phi::visited); | |
2367 return phi; | |
2368 } | |
2369 | |
2370 Value new_opd = simplify(opd); | |
2371 assert(new_opd != NULL, "Simplified operand must exist!"); | |
2372 | |
2373 if (new_opd != phi && new_opd != subst) { | |
2374 if (subst == NULL) { | |
2375 subst = new_opd; | |
2376 } else { | |
2377 // no simplification possible | |
2378 phi->set(Phi::cannot_simplify); | |
2379 phi->clear(Phi::visited); | |
2380 return phi; | |
2381 } | |
2382 } | |
2383 } | |
2384 | |
2385 // sucessfully simplified phi function | |
2386 assert(subst != NULL, "illegal phi function"); | |
2387 _has_substitutions = true; | |
2388 phi->clear(Phi::visited); | |
2389 phi->set_subst(subst); | |
2390 | |
2391 #ifndef PRODUCT | |
2392 if (PrintPhiFunctions) { | |
2393 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()); | |
2394 } | |
2395 #endif | |
2396 | |
2397 return subst; | |
2398 } | |
2399 } | |
2400 | |
2401 | |
2402 void PhiSimplifier::block_do(BlockBegin* b) { | |
2403 for_each_phi_fun(b, phi, | |
2404 simplify(phi); | |
2405 ); | |
2406 | |
2407 #ifdef ASSERT | |
2408 for_each_phi_fun(b, phi, | |
2409 assert(phi->operand_count() != 1 || phi->subst() != phi, "missed trivial simplification"); | |
2410 ); | |
2411 | |
2412 ValueStack* state = b->state()->caller_state(); | |
1819 | 2413 for_each_state_value(state, value, |
2414 Phi* phi = value->as_Phi(); | |
2415 assert(phi == NULL || phi->block() != b, "must not have phi function to simplify in caller state"); | |
2416 ); | |
0 | 2417 #endif |
2418 } | |
2419 | |
2420 // This method is called after all blocks are filled with HIR instructions | |
2421 // It eliminates all Phi functions of the form x = [y, y] and x = [y, x] | |
2422 void GraphBuilder::eliminate_redundant_phis(BlockBegin* start) { | |
2423 PhiSimplifier simplifier(start); | |
2424 } | |
2425 | |
2426 | |
2427 void GraphBuilder::connect_to_end(BlockBegin* beg) { | |
2428 // setup iteration | |
2429 kill_all(); | |
2430 _block = beg; | |
1819 | 2431 _state = beg->state()->copy_for_parsing(); |
0 | 2432 _last = beg; |
2433 iterate_bytecodes_for_block(beg->bci()); | |
2434 } | |
2435 | |
2436 | |
2437 BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { | |
2438 #ifndef PRODUCT | |
2439 if (PrintIRDuringConstruction) { | |
2440 tty->cr(); | |
2441 InstructionPrinter ip; | |
2442 ip.print_instr(_block); tty->cr(); | |
2443 ip.print_stack(_block->state()); tty->cr(); | |
2444 ip.print_inline_level(_block); | |
2445 ip.print_head(); | |
2446 tty->print_cr("locals size: %d stack size: %d", state()->locals_size(), state()->stack_size()); | |
2447 } | |
2448 #endif | |
2449 _skip_block = false; | |
2450 assert(state() != NULL, "ValueStack missing!"); | |
2451 ciBytecodeStream s(method()); | |
2452 s.reset_to_bci(bci); | |
2453 int prev_bci = bci; | |
2454 scope_data()->set_stream(&s); | |
2455 // iterate | |
2456 Bytecodes::Code code = Bytecodes::_illegal; | |
2457 bool push_exception = false; | |
2458 | |
2459 if (block()->is_set(BlockBegin::exception_entry_flag) && block()->next() == NULL) { | |
2460 // first thing in the exception entry block should be the exception object. | |
2461 push_exception = true; | |
2462 } | |
2463 | |
2464 while (!bailed_out() && last()->as_BlockEnd() == NULL && | |
2465 (code = stream()->next()) != ciBytecodeStream::EOBC() && | |
2466 (block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) { | |
1819 | 2467 assert(state()->kind() == ValueStack::Parsing, "invalid state kind"); |
0 | 2468 |
2469 // Check for active jsr during OSR compilation | |
2470 if (compilation()->is_osr_compile() | |
2471 && scope()->is_top_scope() | |
2472 && parsing_jsr() | |
2473 && s.cur_bci() == compilation()->osr_bci()) { | |
2474 bailout("OSR not supported while a jsr is active"); | |
2475 } | |
2476 | |
2477 if (push_exception) { | |
2478 apush(append(new ExceptionObject())); | |
2479 push_exception = false; | |
2480 } | |
2481 | |
2482 // handle bytecode | |
2483 switch (code) { | |
2484 case Bytecodes::_nop : /* nothing to do */ break; | |
2485 case Bytecodes::_aconst_null : apush(append(new Constant(objectNull ))); break; | |
2486 case Bytecodes::_iconst_m1 : ipush(append(new Constant(new IntConstant (-1)))); break; | |
2487 case Bytecodes::_iconst_0 : ipush(append(new Constant(intZero ))); break; | |
2488 case Bytecodes::_iconst_1 : ipush(append(new Constant(intOne ))); break; | |
2489 case Bytecodes::_iconst_2 : ipush(append(new Constant(new IntConstant ( 2)))); break; | |
2490 case Bytecodes::_iconst_3 : ipush(append(new Constant(new IntConstant ( 3)))); break; | |
2491 case Bytecodes::_iconst_4 : ipush(append(new Constant(new IntConstant ( 4)))); break; | |
2492 case Bytecodes::_iconst_5 : ipush(append(new Constant(new IntConstant ( 5)))); break; | |
2493 case Bytecodes::_lconst_0 : lpush(append(new Constant(new LongConstant ( 0)))); break; | |
2494 case Bytecodes::_lconst_1 : lpush(append(new Constant(new LongConstant ( 1)))); break; | |
2495 case Bytecodes::_fconst_0 : fpush(append(new Constant(new FloatConstant ( 0)))); break; | |
2496 case Bytecodes::_fconst_1 : fpush(append(new Constant(new FloatConstant ( 1)))); break; | |
2497 case Bytecodes::_fconst_2 : fpush(append(new Constant(new FloatConstant ( 2)))); break; | |
2498 case Bytecodes::_dconst_0 : dpush(append(new Constant(new DoubleConstant( 0)))); break; | |
2499 case Bytecodes::_dconst_1 : dpush(append(new Constant(new DoubleConstant( 1)))); break; | |
2500 case Bytecodes::_bipush : ipush(append(new Constant(new IntConstant(((signed char*)s.cur_bcp())[1])))); break; | |
2501 case Bytecodes::_sipush : ipush(append(new Constant(new IntConstant((short)Bytes::get_Java_u2(s.cur_bcp()+1))))); break; | |
2502 case Bytecodes::_ldc : // fall through | |
2503 case Bytecodes::_ldc_w : // fall through | |
2504 case Bytecodes::_ldc2_w : load_constant(); break; | |
2505 case Bytecodes::_iload : load_local(intType , s.get_index()); break; | |
2506 case Bytecodes::_lload : load_local(longType , s.get_index()); break; | |
2507 case Bytecodes::_fload : load_local(floatType , s.get_index()); break; | |
2508 case Bytecodes::_dload : load_local(doubleType , s.get_index()); break; | |
2509 case Bytecodes::_aload : load_local(instanceType, s.get_index()); break; | |
2510 case Bytecodes::_iload_0 : load_local(intType , 0); break; | |
2511 case Bytecodes::_iload_1 : load_local(intType , 1); break; | |
2512 case Bytecodes::_iload_2 : load_local(intType , 2); break; | |
2513 case Bytecodes::_iload_3 : load_local(intType , 3); break; | |
2514 case Bytecodes::_lload_0 : load_local(longType , 0); break; | |
2515 case Bytecodes::_lload_1 : load_local(longType , 1); break; | |
2516 case Bytecodes::_lload_2 : load_local(longType , 2); break; | |
2517 case Bytecodes::_lload_3 : load_local(longType , 3); break; | |
2518 case Bytecodes::_fload_0 : load_local(floatType , 0); break; | |
2519 case Bytecodes::_fload_1 : load_local(floatType , 1); break; | |
2520 case Bytecodes::_fload_2 : load_local(floatType , 2); break; | |
2521 case Bytecodes::_fload_3 : load_local(floatType , 3); break; | |
2522 case Bytecodes::_dload_0 : load_local(doubleType, 0); break; | |
2523 case Bytecodes::_dload_1 : load_local(doubleType, 1); break; | |
2524 case Bytecodes::_dload_2 : load_local(doubleType, 2); break; | |
2525 case Bytecodes::_dload_3 : load_local(doubleType, 3); break; | |
2526 case Bytecodes::_aload_0 : load_local(objectType, 0); break; | |
2527 case Bytecodes::_aload_1 : load_local(objectType, 1); break; | |
2528 case Bytecodes::_aload_2 : load_local(objectType, 2); break; | |
2529 case Bytecodes::_aload_3 : load_local(objectType, 3); break; | |
2530 case Bytecodes::_iaload : load_indexed(T_INT ); break; | |
2531 case Bytecodes::_laload : load_indexed(T_LONG ); break; | |
2532 case Bytecodes::_faload : load_indexed(T_FLOAT ); break; | |
2533 case Bytecodes::_daload : load_indexed(T_DOUBLE); break; | |
2534 case Bytecodes::_aaload : load_indexed(T_OBJECT); break; | |
2535 case Bytecodes::_baload : load_indexed(T_BYTE ); break; | |
2536 case Bytecodes::_caload : load_indexed(T_CHAR ); break; | |
2537 case Bytecodes::_saload : load_indexed(T_SHORT ); break; | |
2538 case Bytecodes::_istore : store_local(intType , s.get_index()); break; | |
2539 case Bytecodes::_lstore : store_local(longType , s.get_index()); break; | |
2540 case Bytecodes::_fstore : store_local(floatType , s.get_index()); break; | |
2541 case Bytecodes::_dstore : store_local(doubleType, s.get_index()); break; | |
2542 case Bytecodes::_astore : store_local(objectType, s.get_index()); break; | |
2543 case Bytecodes::_istore_0 : store_local(intType , 0); break; | |
2544 case Bytecodes::_istore_1 : store_local(intType , 1); break; | |
2545 case Bytecodes::_istore_2 : store_local(intType , 2); break; | |
2546 case Bytecodes::_istore_3 : store_local(intType , 3); break; | |
2547 case Bytecodes::_lstore_0 : store_local(longType , 0); break; | |
2548 case Bytecodes::_lstore_1 : store_local(longType , 1); break; | |
2549 case Bytecodes::_lstore_2 : store_local(longType , 2); break; | |
2550 case Bytecodes::_lstore_3 : store_local(longType , 3); break; | |
2551 case Bytecodes::_fstore_0 : store_local(floatType , 0); break; | |
2552 case Bytecodes::_fstore_1 : store_local(floatType , 1); break; | |
2553 case Bytecodes::_fstore_2 : store_local(floatType , 2); break; | |
2554 case Bytecodes::_fstore_3 : store_local(floatType , 3); break; | |
2555 case Bytecodes::_dstore_0 : store_local(doubleType, 0); break; | |
2556 case Bytecodes::_dstore_1 : store_local(doubleType, 1); break; | |
2557 case Bytecodes::_dstore_2 : store_local(doubleType, 2); break; | |
2558 case Bytecodes::_dstore_3 : store_local(doubleType, 3); break; | |
2559 case Bytecodes::_astore_0 : store_local(objectType, 0); break; | |
2560 case Bytecodes::_astore_1 : store_local(objectType, 1); break; | |
2561 case Bytecodes::_astore_2 : store_local(objectType, 2); break; | |
2562 case Bytecodes::_astore_3 : store_local(objectType, 3); break; | |
2563 case Bytecodes::_iastore : store_indexed(T_INT ); break; | |
2564 case Bytecodes::_lastore : store_indexed(T_LONG ); break; | |
2565 case Bytecodes::_fastore : store_indexed(T_FLOAT ); break; | |
2566 case Bytecodes::_dastore : store_indexed(T_DOUBLE); break; | |
2567 case Bytecodes::_aastore : store_indexed(T_OBJECT); break; | |
2568 case Bytecodes::_bastore : store_indexed(T_BYTE ); break; | |
2569 case Bytecodes::_castore : store_indexed(T_CHAR ); break; | |
2570 case Bytecodes::_sastore : store_indexed(T_SHORT ); break; | |
2571 case Bytecodes::_pop : // fall through | |
2572 case Bytecodes::_pop2 : // fall through | |
2573 case Bytecodes::_dup : // fall through | |
2574 case Bytecodes::_dup_x1 : // fall through | |
2575 case Bytecodes::_dup_x2 : // fall through | |
2576 case Bytecodes::_dup2 : // fall through | |
2577 case Bytecodes::_dup2_x1 : // fall through | |
2578 case Bytecodes::_dup2_x2 : // fall through | |
2579 case Bytecodes::_swap : stack_op(code); break; | |
2580 case Bytecodes::_iadd : arithmetic_op(intType , code); break; | |
2581 case Bytecodes::_ladd : arithmetic_op(longType , code); break; | |
2582 case Bytecodes::_fadd : arithmetic_op(floatType , code); break; | |
2583 case Bytecodes::_dadd : arithmetic_op(doubleType, code); break; | |
2584 case Bytecodes::_isub : arithmetic_op(intType , code); break; | |
2585 case Bytecodes::_lsub : arithmetic_op(longType , code); break; | |
2586 case Bytecodes::_fsub : arithmetic_op(floatType , code); break; | |
2587 case Bytecodes::_dsub : arithmetic_op(doubleType, code); break; | |
2588 case Bytecodes::_imul : arithmetic_op(intType , code); break; | |
2589 case Bytecodes::_lmul : arithmetic_op(longType , code); break; | |
2590 case Bytecodes::_fmul : arithmetic_op(floatType , code); break; | |
2591 case Bytecodes::_dmul : arithmetic_op(doubleType, code); break; | |
1819 | 2592 case Bytecodes::_idiv : arithmetic_op(intType , code, copy_state_for_exception()); break; |
2593 case Bytecodes::_ldiv : arithmetic_op(longType , code, copy_state_for_exception()); break; | |
0 | 2594 case Bytecodes::_fdiv : arithmetic_op(floatType , code); break; |
2595 case Bytecodes::_ddiv : arithmetic_op(doubleType, code); break; | |
1819 | 2596 case Bytecodes::_irem : arithmetic_op(intType , code, copy_state_for_exception()); break; |
2597 case Bytecodes::_lrem : arithmetic_op(longType , code, copy_state_for_exception()); break; | |
0 | 2598 case Bytecodes::_frem : arithmetic_op(floatType , code); break; |
2599 case Bytecodes::_drem : arithmetic_op(doubleType, code); break; | |
2600 case Bytecodes::_ineg : negate_op(intType ); break; | |
2601 case Bytecodes::_lneg : negate_op(longType ); break; | |
2602 case Bytecodes::_fneg : negate_op(floatType ); break; | |
2603 case Bytecodes::_dneg : negate_op(doubleType); break; | |
2604 case Bytecodes::_ishl : shift_op(intType , code); break; | |
2605 case Bytecodes::_lshl : shift_op(longType, code); break; | |
2606 case Bytecodes::_ishr : shift_op(intType , code); break; | |
2607 case Bytecodes::_lshr : shift_op(longType, code); break; | |
2608 case Bytecodes::_iushr : shift_op(intType , code); break; | |
2609 case Bytecodes::_lushr : shift_op(longType, code); break; | |
2610 case Bytecodes::_iand : logic_op(intType , code); break; | |
2611 case Bytecodes::_land : logic_op(longType, code); break; | |
2612 case Bytecodes::_ior : logic_op(intType , code); break; | |
2613 case Bytecodes::_lor : logic_op(longType, code); break; | |
2614 case Bytecodes::_ixor : logic_op(intType , code); break; | |
2615 case Bytecodes::_lxor : logic_op(longType, code); break; | |
2616 case Bytecodes::_iinc : increment(); break; | |
2617 case Bytecodes::_i2l : convert(code, T_INT , T_LONG ); break; | |
2618 case Bytecodes::_i2f : convert(code, T_INT , T_FLOAT ); break; | |
2619 case Bytecodes::_i2d : convert(code, T_INT , T_DOUBLE); break; | |
2620 case Bytecodes::_l2i : convert(code, T_LONG , T_INT ); break; | |
2621 case Bytecodes::_l2f : convert(code, T_LONG , T_FLOAT ); break; | |
2622 case Bytecodes::_l2d : convert(code, T_LONG , T_DOUBLE); break; | |
2623 case Bytecodes::_f2i : convert(code, T_FLOAT , T_INT ); break; | |
2624 case Bytecodes::_f2l : convert(code, T_FLOAT , T_LONG ); break; | |
2625 case Bytecodes::_f2d : convert(code, T_FLOAT , T_DOUBLE); break; | |
2626 case Bytecodes::_d2i : convert(code, T_DOUBLE, T_INT ); break; | |
2627 case Bytecodes::_d2l : convert(code, T_DOUBLE, T_LONG ); break; | |
2628 case Bytecodes::_d2f : convert(code, T_DOUBLE, T_FLOAT ); break; | |
2629 case Bytecodes::_i2b : convert(code, T_INT , T_BYTE ); break; | |
2630 case Bytecodes::_i2c : convert(code, T_INT , T_CHAR ); break; | |
2631 case Bytecodes::_i2s : convert(code, T_INT , T_SHORT ); break; | |
2632 case Bytecodes::_lcmp : compare_op(longType , code); break; | |
2633 case Bytecodes::_fcmpl : compare_op(floatType , code); break; | |
2634 case Bytecodes::_fcmpg : compare_op(floatType , code); break; | |
2635 case Bytecodes::_dcmpl : compare_op(doubleType, code); break; | |
2636 case Bytecodes::_dcmpg : compare_op(doubleType, code); break; | |
2637 case Bytecodes::_ifeq : if_zero(intType , If::eql); break; | |
2638 case Bytecodes::_ifne : if_zero(intType , If::neq); break; | |
2639 case Bytecodes::_iflt : if_zero(intType , If::lss); break; | |
2640 case Bytecodes::_ifge : if_zero(intType , If::geq); break; | |
2641 case Bytecodes::_ifgt : if_zero(intType , If::gtr); break; | |
2642 case Bytecodes::_ifle : if_zero(intType , If::leq); break; | |
2643 case Bytecodes::_if_icmpeq : if_same(intType , If::eql); break; | |
2644 case Bytecodes::_if_icmpne : if_same(intType , If::neq); break; | |
2645 case Bytecodes::_if_icmplt : if_same(intType , If::lss); break; | |
2646 case Bytecodes::_if_icmpge : if_same(intType , If::geq); break; | |
2647 case Bytecodes::_if_icmpgt : if_same(intType , If::gtr); break; | |
2648 case Bytecodes::_if_icmple : if_same(intType , If::leq); break; | |
2649 case Bytecodes::_if_acmpeq : if_same(objectType, If::eql); break; | |
2650 case Bytecodes::_if_acmpne : if_same(objectType, If::neq); break; | |
2651 case Bytecodes::_goto : _goto(s.cur_bci(), s.get_dest()); break; | |
2652 case Bytecodes::_jsr : jsr(s.get_dest()); break; | |
2653 case Bytecodes::_ret : ret(s.get_index()); break; | |
2654 case Bytecodes::_tableswitch : table_switch(); break; | |
2655 case Bytecodes::_lookupswitch : lookup_switch(); break; | |
2656 case Bytecodes::_ireturn : method_return(ipop()); break; | |
2657 case Bytecodes::_lreturn : method_return(lpop()); break; | |
2658 case Bytecodes::_freturn : method_return(fpop()); break; | |
2659 case Bytecodes::_dreturn : method_return(dpop()); break; | |
2660 case Bytecodes::_areturn : method_return(apop()); break; | |
2661 case Bytecodes::_return : method_return(NULL ); break; | |
2662 case Bytecodes::_getstatic : // fall through | |
2663 case Bytecodes::_putstatic : // fall through | |
2664 case Bytecodes::_getfield : // fall through | |
2665 case Bytecodes::_putfield : access_field(code); break; | |
2666 case Bytecodes::_invokevirtual : // fall through | |
2667 case Bytecodes::_invokespecial : // fall through | |
2668 case Bytecodes::_invokestatic : // fall through | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
470
diff
changeset
|
2669 case Bytecodes::_invokedynamic : // fall through |
0 | 2670 case Bytecodes::_invokeinterface: invoke(code); break; |
1565 | 2671 case Bytecodes::_new : new_instance(s.get_index_u2()); break; |
0 | 2672 case Bytecodes::_newarray : new_type_array(); break; |
2673 case Bytecodes::_anewarray : new_object_array(); break; | |
1819 | 2674 case Bytecodes::_arraylength : { ValueStack* state_before = copy_state_for_exception(); ipush(append(new ArrayLength(apop(), state_before))); break; } |
0 | 2675 case Bytecodes::_athrow : throw_op(s.cur_bci()); break; |
1565 | 2676 case Bytecodes::_checkcast : check_cast(s.get_index_u2()); break; |
2677 case Bytecodes::_instanceof : instance_of(s.get_index_u2()); break; | |
0 | 2678 case Bytecodes::_monitorenter : monitorenter(apop(), s.cur_bci()); break; |
2679 case Bytecodes::_monitorexit : monitorexit (apop(), s.cur_bci()); break; | |
2680 case Bytecodes::_wide : ShouldNotReachHere(); break; | |
2681 case Bytecodes::_multianewarray : new_multi_array(s.cur_bcp()[3]); break; | |
2682 case Bytecodes::_ifnull : if_null(objectType, If::eql); break; | |
2683 case Bytecodes::_ifnonnull : if_null(objectType, If::neq); break; | |
2684 case Bytecodes::_goto_w : _goto(s.cur_bci(), s.get_far_dest()); break; | |
2685 case Bytecodes::_jsr_w : jsr(s.get_far_dest()); break; | |
2686 case Bytecodes::_breakpoint : BAILOUT_("concurrent setting of breakpoint", NULL); | |
2687 default : ShouldNotReachHere(); break; | |
2688 } | |
2689 // save current bci to setup Goto at the end | |
2690 prev_bci = s.cur_bci(); | |
2691 } | |
2692 CHECK_BAILOUT_(NULL); | |
2693 // stop processing of this block (see try_inline_full) | |
2694 if (_skip_block) { | |
2695 _skip_block = false; | |
2696 assert(_last && _last->as_BlockEnd(), ""); | |
2697 return _last->as_BlockEnd(); | |
2698 } | |
2699 // if there are any, check if last instruction is a BlockEnd instruction | |
2700 BlockEnd* end = last()->as_BlockEnd(); | |
2701 if (end == NULL) { | |
2702 // all blocks must end with a BlockEnd instruction => add a Goto | |
2703 end = new Goto(block_at(s.cur_bci()), false); | |
1819 | 2704 append(end); |
0 | 2705 } |
2706 assert(end == last()->as_BlockEnd(), "inconsistency"); | |
2707 | |
1819 | 2708 assert(end->state() != NULL, "state must already be present"); |
2709 assert(end->as_Return() == NULL || end->as_Throw() == NULL || end->state()->stack_size() == 0, "stack not needed for return and throw"); | |
0 | 2710 |
2711 // connect to begin & set state | |
2712 // NOTE that inlining may have changed the block we are parsing | |
2713 block()->set_end(end); | |
2714 // propagate state | |
2715 for (int i = end->number_of_sux() - 1; i >= 0; i--) { | |
2716 BlockBegin* sux = end->sux_at(i); | |
2717 assert(sux->is_predecessor(block()), "predecessor missing"); | |
2718 // be careful, bailout if bytecodes are strange | |
1819 | 2719 if (!sux->try_merge(end->state())) BAILOUT_("block join failed", NULL); |
0 | 2720 scope_data()->add_to_work_list(end->sux_at(i)); |
2721 } | |
2722 | |
2723 scope_data()->set_stream(NULL); | |
2724 | |
2725 // done | |
2726 return end; | |
2727 } | |
2728 | |
2729 | |
2730 void GraphBuilder::iterate_all_blocks(bool start_in_current_block_for_inlining) { | |
2731 do { | |
2732 if (start_in_current_block_for_inlining && !bailed_out()) { | |
2733 iterate_bytecodes_for_block(0); | |
2734 start_in_current_block_for_inlining = false; | |
2735 } else { | |
2736 BlockBegin* b; | |
2737 while ((b = scope_data()->remove_from_work_list()) != NULL) { | |
2738 if (!b->is_set(BlockBegin::was_visited_flag)) { | |
2739 if (b->is_set(BlockBegin::osr_entry_flag)) { | |
2740 // we're about to parse the osr entry block, so make sure | |
2741 // we setup the OSR edge leading into this block so that | |
2742 // Phis get setup correctly. | |
2743 setup_osr_entry_block(); | |
2744 // this is no longer the osr entry block, so clear it. | |
2745 b->clear(BlockBegin::osr_entry_flag); | |
2746 } | |
2747 b->set(BlockBegin::was_visited_flag); | |
2748 connect_to_end(b); | |
2749 } | |
2750 } | |
2751 } | |
2752 } while (!bailed_out() && !scope_data()->is_work_list_empty()); | |
2753 } | |
2754 | |
2755 | |
2756 bool GraphBuilder::_can_trap [Bytecodes::number_of_java_codes]; | |
2757 | |
2758 void GraphBuilder::initialize() { | |
2759 // the following bytecodes are assumed to potentially | |
2760 // throw exceptions in compiled code - note that e.g. | |
2761 // monitorexit & the return bytecodes do not throw | |
2762 // exceptions since monitor pairing proved that they | |
2763 // succeed (if monitor pairing succeeded) | |
2764 Bytecodes::Code can_trap_list[] = | |
2765 { Bytecodes::_ldc | |
2766 , Bytecodes::_ldc_w | |
2767 , Bytecodes::_ldc2_w | |
2768 , Bytecodes::_iaload | |
2769 , Bytecodes::_laload | |
2770 , Bytecodes::_faload | |
2771 , Bytecodes::_daload | |
2772 , Bytecodes::_aaload | |
2773 , Bytecodes::_baload | |
2774 , Bytecodes::_caload | |
2775 , Bytecodes::_saload | |
2776 , Bytecodes::_iastore | |
2777 , Bytecodes::_lastore | |
2778 , Bytecodes::_fastore | |
2779 , Bytecodes::_dastore | |
2780 , Bytecodes::_aastore | |
2781 , Bytecodes::_bastore | |
2782 , Bytecodes::_castore | |
2783 , Bytecodes::_sastore | |
2784 , Bytecodes::_idiv | |
2785 , Bytecodes::_ldiv | |
2786 , Bytecodes::_irem | |
2787 , Bytecodes::_lrem | |
2788 , Bytecodes::_getstatic | |
2789 , Bytecodes::_putstatic | |
2790 , Bytecodes::_getfield | |
2791 , Bytecodes::_putfield | |
2792 , Bytecodes::_invokevirtual | |
2793 , Bytecodes::_invokespecial | |
2794 , Bytecodes::_invokestatic | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
470
diff
changeset
|
2795 , Bytecodes::_invokedynamic |
0 | 2796 , Bytecodes::_invokeinterface |
2797 , Bytecodes::_new | |
2798 , Bytecodes::_newarray | |
2799 , Bytecodes::_anewarray | |
2800 , Bytecodes::_arraylength | |
2801 , Bytecodes::_athrow | |
2802 , Bytecodes::_checkcast | |
2803 , Bytecodes::_instanceof | |
2804 , Bytecodes::_monitorenter | |
2805 , Bytecodes::_multianewarray | |
2806 }; | |
2807 | |
2808 // inititialize trap tables | |
2809 for (int i = 0; i < Bytecodes::number_of_java_codes; i++) { | |
2810 _can_trap[i] = false; | |
2811 } | |
2812 // set standard trap info | |
2813 for (uint j = 0; j < ARRAY_SIZE(can_trap_list); j++) { | |
2814 _can_trap[can_trap_list[j]] = true; | |
2815 } | |
2816 } | |
2817 | |
2818 | |
2819 BlockBegin* GraphBuilder::header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state) { | |
2820 assert(entry->is_set(f), "entry/flag mismatch"); | |
2821 // create header block | |
2822 BlockBegin* h = new BlockBegin(entry->bci()); | |
2823 h->set_depth_first_number(0); | |
2824 | |
2825 Value l = h; | |
2826 BlockEnd* g = new Goto(entry, false); | |
2827 l->set_next(g, entry->bci()); | |
2828 h->set_end(g); | |
2829 h->set(f); | |
2830 // setup header block end state | |
1819 | 2831 ValueStack* s = state->copy(ValueStack::StateAfter, entry->bci()); // can use copy since stack is empty (=> no phis) |
0 | 2832 assert(s->stack_is_empty(), "must have empty stack at entry point"); |
2833 g->set_state(s); | |
2834 return h; | |
2835 } | |
2836 | |
2837 | |
2838 | |
2839 BlockBegin* GraphBuilder::setup_start_block(int osr_bci, BlockBegin* std_entry, BlockBegin* osr_entry, ValueStack* state) { | |
2840 BlockBegin* start = new BlockBegin(0); | |
2841 | |
2842 // This code eliminates the empty start block at the beginning of | |
2843 // each method. Previously, each method started with the | |
2844 // start-block created below, and this block was followed by the | |
2845 // header block that was always empty. This header block is only | |
2846 // necesary if std_entry is also a backward branch target because | |
2847 // then phi functions may be necessary in the header block. It's | |
2848 // also necessary when profiling so that there's a single block that | |
2849 // can increment the interpreter_invocation_count. | |
2850 BlockBegin* new_header_block; | |
1783 | 2851 if (std_entry->number_of_preds() > 0 || count_invocations() || count_backedges()) { |
2852 new_header_block = header_block(std_entry, BlockBegin::std_entry_flag, state); | |
2853 } else { | |
0 | 2854 new_header_block = std_entry; |
2855 } | |
2856 | |
2857 // setup start block (root for the IR graph) | |
2858 Base* base = | |
2859 new Base( | |
2860 new_header_block, | |
2861 osr_entry | |
2862 ); | |
2863 start->set_next(base, 0); | |
2864 start->set_end(base); | |
2865 // create & setup state for start block | |
1819 | 2866 start->set_state(state->copy(ValueStack::StateAfter, std_entry->bci())); |
2867 base->set_state(state->copy(ValueStack::StateAfter, std_entry->bci())); | |
0 | 2868 |
2869 if (base->std_entry()->state() == NULL) { | |
2870 // setup states for header blocks | |
2871 base->std_entry()->merge(state); | |
2872 } | |
2873 | |
2874 assert(base->std_entry()->state() != NULL, ""); | |
2875 return start; | |
2876 } | |
2877 | |
2878 | |
2879 void GraphBuilder::setup_osr_entry_block() { | |
2880 assert(compilation()->is_osr_compile(), "only for osrs"); | |
2881 | |
2882 int osr_bci = compilation()->osr_bci(); | |
2883 ciBytecodeStream s(method()); | |
2884 s.reset_to_bci(osr_bci); | |
2885 s.next(); | |
2886 scope_data()->set_stream(&s); | |
2887 | |
2888 // create a new block to be the osr setup code | |
2889 _osr_entry = new BlockBegin(osr_bci); | |
2890 _osr_entry->set(BlockBegin::osr_entry_flag); | |
2891 _osr_entry->set_depth_first_number(0); | |
2892 BlockBegin* target = bci2block()->at(osr_bci); | |
2893 assert(target != NULL && target->is_set(BlockBegin::osr_entry_flag), "must be there"); | |
2894 // the osr entry has no values for locals | |
2895 ValueStack* state = target->state()->copy(); | |
2896 _osr_entry->set_state(state); | |
2897 | |
2898 kill_all(); | |
2899 _block = _osr_entry; | |
2900 _state = _osr_entry->state()->copy(); | |
1819 | 2901 assert(_state->bci() == osr_bci, "mismatch"); |
0 | 2902 _last = _osr_entry; |
2903 Value e = append(new OsrEntry()); | |
2904 e->set_needs_null_check(false); | |
2905 | |
2906 // OSR buffer is | |
2907 // | |
2908 // locals[nlocals-1..0] | |
2909 // monitors[number_of_locks-1..0] | |
2910 // | |
2911 // locals is a direct copy of the interpreter frame so in the osr buffer | |
2912 // so first slot in the local array is the last local from the interpreter | |
2913 // and last slot is local[0] (receiver) from the interpreter | |
2914 // | |
2915 // Similarly with locks. The first lock slot in the osr buffer is the nth lock | |
2916 // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock | |
2917 // in the interpreter frame (the method lock if a sync method) | |
2918 | |
2919 // Initialize monitors in the compiled activation. | |
2920 | |
2921 int index; | |
2922 Value local; | |
2923 | |
2924 // find all the locals that the interpreter thinks contain live oops | |
2925 const BitMap live_oops = method()->live_local_oops_at_bci(osr_bci); | |
2926 | |
2927 // compute the offset into the locals so that we can treat the buffer | |
2928 // as if the locals were still in the interpreter frame | |
2929 int locals_offset = BytesPerWord * (method()->max_locals() - 1); | |
2930 for_each_local_value(state, index, local) { | |
2931 int offset = locals_offset - (index + local->type()->size() - 1) * BytesPerWord; | |
2932 Value get; | |
2933 if (local->type()->is_object_kind() && !live_oops.at(index)) { | |
2934 // The interpreter thinks this local is dead but the compiler | |
2935 // doesn't so pretend that the interpreter passed in null. | |
2936 get = append(new Constant(objectNull)); | |
2937 } else { | |
2938 get = append(new UnsafeGetRaw(as_BasicType(local->type()), e, | |
2939 append(new Constant(new IntConstant(offset))), | |
2940 0, | |
2002 | 2941 true /*unaligned*/, true /*wide*/)); |
0 | 2942 } |
2943 _state->store_local(index, get); | |
2944 } | |
2945 | |
2946 // the storage for the OSR buffer is freed manually in the LIRGenerator. | |
2947 | |
2948 assert(state->caller_state() == NULL, "should be top scope"); | |
2949 state->clear_locals(); | |
2950 Goto* g = new Goto(target, false); | |
2951 append(g); | |
2952 _osr_entry->set_end(g); | |
2953 target->merge(_osr_entry->end()->state()); | |
2954 | |
2955 scope_data()->set_stream(NULL); | |
2956 } | |
2957 | |
2958 | |
2959 ValueStack* GraphBuilder::state_at_entry() { | |
1819 | 2960 ValueStack* state = new ValueStack(scope(), NULL); |
0 | 2961 |
2962 // Set up locals for receiver | |
2963 int idx = 0; | |
2964 if (!method()->is_static()) { | |
2965 // we should always see the receiver | |
2446 | 2966 state->store_local(idx, new Local(method()->holder(), objectType, idx)); |
0 | 2967 idx = 1; |
2968 } | |
2969 | |
2970 // Set up locals for incoming arguments | |
2971 ciSignature* sig = method()->signature(); | |
2972 for (int i = 0; i < sig->count(); i++) { | |
2973 ciType* type = sig->type_at(i); | |
2974 BasicType basic_type = type->basic_type(); | |
2975 // don't allow T_ARRAY to propagate into locals types | |
2976 if (basic_type == T_ARRAY) basic_type = T_OBJECT; | |
2977 ValueType* vt = as_ValueType(basic_type); | |
2446 | 2978 state->store_local(idx, new Local(type, vt, idx)); |
0 | 2979 idx += type->size(); |
2980 } | |
2981 | |
2982 // lock synchronized method | |
2983 if (method()->is_synchronized()) { | |
1819 | 2984 state->lock(NULL); |
0 | 2985 } |
2986 | |
2987 return state; | |
2988 } | |
2989 | |
2990 | |
2991 GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) | |
2992 : _scope_data(NULL) | |
2993 , _instruction_count(0) | |
2994 , _osr_entry(NULL) | |
2995 , _memory(new MemoryBuffer()) | |
2996 , _compilation(compilation) | |
2997 , _inline_bailout_msg(NULL) | |
2998 { | |
2999 int osr_bci = compilation->osr_bci(); | |
3000 | |
3001 // determine entry points and bci2block mapping | |
3002 BlockListBuilder blm(compilation, scope, osr_bci); | |
3003 CHECK_BAILOUT(); | |
3004 | |
3005 BlockList* bci2block = blm.bci2block(); | |
3006 BlockBegin* start_block = bci2block->at(0); | |
3007 | |
3008 push_root_scope(scope, bci2block, start_block); | |
3009 | |
3010 // setup state for std entry | |
3011 _initial_state = state_at_entry(); | |
3012 start_block->merge(_initial_state); | |
3013 | |
3014 // complete graph | |
3015 _vmap = new ValueMap(); | |
3016 switch (scope->method()->intrinsic_id()) { | |
3017 case vmIntrinsics::_dabs : // fall through | |
3018 case vmIntrinsics::_dsqrt : // fall through | |
3019 case vmIntrinsics::_dsin : // fall through | |
3020 case vmIntrinsics::_dcos : // fall through | |
3021 case vmIntrinsics::_dtan : // fall through | |
3022 case vmIntrinsics::_dlog : // fall through | |
3023 case vmIntrinsics::_dlog10 : // fall through | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3024 case vmIntrinsics::_dexp : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3025 case vmIntrinsics::_dpow : // fall through |
0 | 3026 { |
3027 // Compiles where the root method is an intrinsic need a special | |
3028 // compilation environment because the bytecodes for the method | |
3029 // shouldn't be parsed during the compilation, only the special | |
3030 // Intrinsic node should be emitted. If this isn't done the the | |
3031 // code for the inlined version will be different than the root | |
3032 // compiled version which could lead to monotonicity problems on | |
3033 // intel. | |
3034 | |
3035 // Set up a stream so that appending instructions works properly. | |
3036 ciBytecodeStream s(scope->method()); | |
3037 s.reset_to_bci(0); | |
3038 scope_data()->set_stream(&s); | |
3039 s.next(); | |
3040 | |
3041 // setup the initial block state | |
3042 _block = start_block; | |
1819 | 3043 _state = start_block->state()->copy_for_parsing(); |
0 | 3044 _last = start_block; |
3045 load_local(doubleType, 0); | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3046 if (scope->method()->intrinsic_id() == vmIntrinsics::_dpow) { |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3047 load_local(doubleType, 2); |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3048 } |
0 | 3049 |
3050 // Emit the intrinsic node. | |
3051 bool result = try_inline_intrinsics(scope->method()); | |
3052 if (!result) BAILOUT("failed to inline intrinsic"); | |
3053 method_return(dpop()); | |
3054 | |
3055 // connect the begin and end blocks and we're all done. | |
3056 BlockEnd* end = last()->as_BlockEnd(); | |
3057 block()->set_end(end); | |
3058 break; | |
3059 } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3060 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3061 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3062 { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3063 { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3064 // 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
|
3065 // 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
|
3066 // 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
|
3067 // 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
|
3068 // the pre-barrier code. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3069 // 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
|
3070 // 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
|
3071 // 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
|
3072 // 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
|
3073 // reference processing. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3074 |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3075 // 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
|
3076 // 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
|
3077 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3078 // 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
|
3079 ciBytecodeStream s(scope->method()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3080 s.reset_to_bci(0); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3081 scope_data()->set_stream(&s); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3082 s.next(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3083 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3084 // setup the initial block state |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3085 _block = start_block; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3086 _state = start_block->state()->copy_for_parsing(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3087 _last = start_block; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3088 load_local(objectType, 0); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3089 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3090 // Emit the intrinsic node. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3091 bool result = try_inline_intrinsics(scope->method()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3092 if (!result) BAILOUT("failed to inline intrinsic"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3093 method_return(apop()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3094 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3095 // 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
|
3096 BlockEnd* end = last()->as_BlockEnd(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3097 block()->set_end(end); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3098 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3099 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3100 // Otherwise, fall thru |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3101 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3102 |
0 | 3103 default: |
3104 scope_data()->add_to_work_list(start_block); | |
3105 iterate_all_blocks(); | |
3106 break; | |
3107 } | |
3108 CHECK_BAILOUT(); | |
3109 | |
3110 _start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state); | |
3111 | |
3112 eliminate_redundant_phis(_start); | |
3113 | |
3114 NOT_PRODUCT(if (PrintValueNumbering && Verbose) print_stats()); | |
3115 // for osr compile, bailout if some requirements are not fulfilled | |
3116 if (osr_bci != -1) { | |
3117 BlockBegin* osr_block = blm.bci2block()->at(osr_bci); | |
3118 assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile"); | |
3119 | |
3120 // check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points | |
3121 if (!osr_block->state()->stack_is_empty()) { | |
3122 BAILOUT("stack not empty at OSR entry point"); | |
3123 } | |
3124 } | |
3125 #ifndef PRODUCT | |
3126 if (PrintCompilation && Verbose) tty->print_cr("Created %d Instructions", _instruction_count); | |
3127 #endif | |
3128 } | |
3129 | |
3130 | |
1819 | 3131 ValueStack* GraphBuilder::copy_state_before() { |
3132 return copy_state_before_with_bci(bci()); | |
3133 } | |
3134 | |
3135 ValueStack* GraphBuilder::copy_state_exhandling() { | |
3136 return copy_state_exhandling_with_bci(bci()); | |
3137 } | |
3138 | |
3139 ValueStack* GraphBuilder::copy_state_for_exception() { | |
3140 return copy_state_for_exception_with_bci(bci()); | |
3141 } | |
3142 | |
3143 ValueStack* GraphBuilder::copy_state_before_with_bci(int bci) { | |
3144 return state()->copy(ValueStack::StateBefore, bci); | |
0 | 3145 } |
3146 | |
1819 | 3147 ValueStack* GraphBuilder::copy_state_exhandling_with_bci(int bci) { |
3148 if (!has_handler()) return NULL; | |
3149 return state()->copy(ValueStack::StateBefore, bci); | |
3150 } | |
3151 | |
3152 ValueStack* GraphBuilder::copy_state_for_exception_with_bci(int bci) { | |
3153 ValueStack* s = copy_state_exhandling_with_bci(bci); | |
3154 if (s == NULL) { | |
3155 if (_compilation->env()->jvmti_can_access_local_variables()) { | |
3156 s = state()->copy(ValueStack::ExceptionState, bci); | |
3157 } else { | |
3158 s = state()->copy(ValueStack::EmptyExceptionState, bci); | |
3159 } | |
3160 } | |
3161 return s; | |
3162 } | |
0 | 3163 |
3164 int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const { | |
3165 int recur_level = 0; | |
3166 for (IRScope* s = scope(); s != NULL; s = s->caller()) { | |
3167 if (s->method() == cur_callee) { | |
3168 ++recur_level; | |
3169 } | |
3170 } | |
3171 return recur_level; | |
3172 } | |
3173 | |
3174 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3175 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
|
3176 const char* msg = NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3177 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3178 // clear out any existing inline bailout condition |
0 | 3179 clear_inline_bailout(); |
3180 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3181 // 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
|
3182 msg = should_not_inline(callee); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3183 if (msg != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3184 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
|
3185 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3186 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3187 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3188 // handle intrinsics |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3189 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
|
3190 if (try_inline_intrinsics(callee)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3191 print_inlining(callee, "intrinsic"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3192 return true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3193 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3194 // try normal inlining |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3195 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3196 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3197 // 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
|
3198 msg = check_can_parse(callee); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3199 if (msg != NULL) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3200 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
|
3201 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3202 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3203 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3204 // 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
|
3205 if (bc == Bytecodes::_illegal) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3206 bc = code(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3207 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3208 if (try_inline_full(callee, holder_known, bc, receiver)) |
0 | 3209 return true; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3210 print_inlining(callee, _inline_bailout_msg, /*success*/ false); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3211 return false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3212 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3213 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3214 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3215 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
|
3216 // 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
|
3217 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
|
3218 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
|
3219 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
|
3220 return NULL; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3221 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3222 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3223 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3224 // 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
|
3225 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
|
3226 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
|
3227 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
|
3228 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
|
3229 return NULL; |
0 | 3230 } |
3231 | |
3232 | |
3233 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
|
3234 if (callee->is_synchronized()) { |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3235 // 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
|
3236 return false; |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3237 } |
99791ad65936
6953539: after 6892658 c1 reports that it doesn't inline StringBuffer.append
never
parents:
1397
diff
changeset
|
3238 |
0 | 3239 // callee seems like a good candidate |
3240 // determine id | |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3241 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
|
3242 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
|
3243 // 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
|
3244 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
|
3245 } |
0 | 3246 bool preserves_state = false; |
3247 bool cantrap = true; | |
3248 switch (id) { | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3249 case vmIntrinsics::_arraycopy: |
0 | 3250 if (!InlineArrayCopy) return false; |
3251 break; | |
3252 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3253 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3254 case vmIntrinsics::_classID: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3255 case vmIntrinsics::_threadID: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3256 preserves_state = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3257 cantrap = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3258 break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3259 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3260 case vmIntrinsics::_counterTime: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3261 preserves_state = true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3262 cantrap = false; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3263 break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3264 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5998
diff
changeset
|
3265 |
0 | 3266 case vmIntrinsics::_currentTimeMillis: |
3267 case vmIntrinsics::_nanoTime: | |
3268 preserves_state = true; | |
3269 cantrap = false; | |
3270 break; | |
3271 | |
3272 case vmIntrinsics::_floatToRawIntBits : | |
3273 case vmIntrinsics::_intBitsToFloat : | |
3274 case vmIntrinsics::_doubleToRawLongBits : | |
3275 case vmIntrinsics::_longBitsToDouble : | |
3276 if (!InlineMathNatives) return false; | |
3277 preserves_state = true; | |
3278 cantrap = false; | |
3279 break; | |
3280 | |
3281 case vmIntrinsics::_getClass : | |
6135 | 3282 case vmIntrinsics::_isInstance : |
0 | 3283 if (!InlineClassNatives) return false; |
3284 preserves_state = true; | |
3285 break; | |
3286 | |
3287 case vmIntrinsics::_currentThread : | |
3288 if (!InlineThreadNatives) return false; | |
3289 preserves_state = true; | |
3290 cantrap = false; | |
3291 break; | |
3292 | |
3293 case vmIntrinsics::_dabs : // fall through | |
3294 case vmIntrinsics::_dsqrt : // fall through | |
3295 case vmIntrinsics::_dsin : // fall through | |
3296 case vmIntrinsics::_dcos : // fall through | |
3297 case vmIntrinsics::_dtan : // fall through | |
3298 case vmIntrinsics::_dlog : // fall through | |
3299 case vmIntrinsics::_dlog10 : // fall through | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3300 case vmIntrinsics::_dexp : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3301 case vmIntrinsics::_dpow : // fall through |
0 | 3302 if (!InlineMathNatives) return false; |
3303 cantrap = false; | |
3304 preserves_state = true; | |
3305 break; | |
3306 | |
3307 // Use special nodes for Unsafe instructions so we can more easily | |
3308 // perform an address-mode optimization on the raw variants | |
3309 case vmIntrinsics::_getObject : return append_unsafe_get_obj(callee, T_OBJECT, false); | |
3310 case vmIntrinsics::_getBoolean: return append_unsafe_get_obj(callee, T_BOOLEAN, false); | |
3311 case vmIntrinsics::_getByte : return append_unsafe_get_obj(callee, T_BYTE, false); | |
3312 case vmIntrinsics::_getShort : return append_unsafe_get_obj(callee, T_SHORT, false); | |
3313 case vmIntrinsics::_getChar : return append_unsafe_get_obj(callee, T_CHAR, false); | |
3314 case vmIntrinsics::_getInt : return append_unsafe_get_obj(callee, T_INT, false); | |
3315 case vmIntrinsics::_getLong : return append_unsafe_get_obj(callee, T_LONG, false); | |
3316 case vmIntrinsics::_getFloat : return append_unsafe_get_obj(callee, T_FLOAT, false); | |
3317 case vmIntrinsics::_getDouble : return append_unsafe_get_obj(callee, T_DOUBLE, false); | |
3318 | |
3319 case vmIntrinsics::_putObject : return append_unsafe_put_obj(callee, T_OBJECT, false); | |
3320 case vmIntrinsics::_putBoolean: return append_unsafe_put_obj(callee, T_BOOLEAN, false); | |
3321 case vmIntrinsics::_putByte : return append_unsafe_put_obj(callee, T_BYTE, false); | |
3322 case vmIntrinsics::_putShort : return append_unsafe_put_obj(callee, T_SHORT, false); | |
3323 case vmIntrinsics::_putChar : return append_unsafe_put_obj(callee, T_CHAR, false); | |
3324 case vmIntrinsics::_putInt : return append_unsafe_put_obj(callee, T_INT, false); | |
3325 case vmIntrinsics::_putLong : return append_unsafe_put_obj(callee, T_LONG, false); | |
3326 case vmIntrinsics::_putFloat : return append_unsafe_put_obj(callee, T_FLOAT, false); | |
3327 case vmIntrinsics::_putDouble : return append_unsafe_put_obj(callee, T_DOUBLE, false); | |
3328 | |
3329 case vmIntrinsics::_getObjectVolatile : return append_unsafe_get_obj(callee, T_OBJECT, true); | |
3330 case vmIntrinsics::_getBooleanVolatile: return append_unsafe_get_obj(callee, T_BOOLEAN, true); | |
3331 case vmIntrinsics::_getByteVolatile : return append_unsafe_get_obj(callee, T_BYTE, true); | |
3332 case vmIntrinsics::_getShortVolatile : return append_unsafe_get_obj(callee, T_SHORT, true); | |
3333 case vmIntrinsics::_getCharVolatile : return append_unsafe_get_obj(callee, T_CHAR, true); | |
3334 case vmIntrinsics::_getIntVolatile : return append_unsafe_get_obj(callee, T_INT, true); | |
3335 case vmIntrinsics::_getLongVolatile : return append_unsafe_get_obj(callee, T_LONG, true); | |
3336 case vmIntrinsics::_getFloatVolatile : return append_unsafe_get_obj(callee, T_FLOAT, true); | |
3337 case vmIntrinsics::_getDoubleVolatile : return append_unsafe_get_obj(callee, T_DOUBLE, true); | |
3338 | |
3339 case vmIntrinsics::_putObjectVolatile : return append_unsafe_put_obj(callee, T_OBJECT, true); | |
3340 case vmIntrinsics::_putBooleanVolatile: return append_unsafe_put_obj(callee, T_BOOLEAN, true); | |
3341 case vmIntrinsics::_putByteVolatile : return append_unsafe_put_obj(callee, T_BYTE, true); | |
3342 case vmIntrinsics::_putShortVolatile : return append_unsafe_put_obj(callee, T_SHORT, true); | |
3343 case vmIntrinsics::_putCharVolatile : return append_unsafe_put_obj(callee, T_CHAR, true); | |
3344 case vmIntrinsics::_putIntVolatile : return append_unsafe_put_obj(callee, T_INT, true); | |
3345 case vmIntrinsics::_putLongVolatile : return append_unsafe_put_obj(callee, T_LONG, true); | |
3346 case vmIntrinsics::_putFloatVolatile : return append_unsafe_put_obj(callee, T_FLOAT, true); | |
3347 case vmIntrinsics::_putDoubleVolatile : return append_unsafe_put_obj(callee, T_DOUBLE, true); | |
3348 | |
3349 case vmIntrinsics::_getByte_raw : return append_unsafe_get_raw(callee, T_BYTE); | |
3350 case vmIntrinsics::_getShort_raw : return append_unsafe_get_raw(callee, T_SHORT); | |
3351 case vmIntrinsics::_getChar_raw : return append_unsafe_get_raw(callee, T_CHAR); | |
3352 case vmIntrinsics::_getInt_raw : return append_unsafe_get_raw(callee, T_INT); | |
3353 case vmIntrinsics::_getLong_raw : return append_unsafe_get_raw(callee, T_LONG); | |
3354 case vmIntrinsics::_getFloat_raw : return append_unsafe_get_raw(callee, T_FLOAT); | |
3355 case vmIntrinsics::_getDouble_raw : return append_unsafe_get_raw(callee, T_DOUBLE); | |
3356 | |
3357 case vmIntrinsics::_putByte_raw : return append_unsafe_put_raw(callee, T_BYTE); | |
3358 case vmIntrinsics::_putShort_raw : return append_unsafe_put_raw(callee, T_SHORT); | |
3359 case vmIntrinsics::_putChar_raw : return append_unsafe_put_raw(callee, T_CHAR); | |
3360 case vmIntrinsics::_putInt_raw : return append_unsafe_put_raw(callee, T_INT); | |
3361 case vmIntrinsics::_putLong_raw : return append_unsafe_put_raw(callee, T_LONG); | |
3362 case vmIntrinsics::_putFloat_raw : return append_unsafe_put_raw(callee, T_FLOAT); | |
3363 case vmIntrinsics::_putDouble_raw : return append_unsafe_put_raw(callee, T_DOUBLE); | |
3364 | |
3365 case vmIntrinsics::_prefetchRead : return append_unsafe_prefetch(callee, false, false); | |
3366 case vmIntrinsics::_prefetchWrite : return append_unsafe_prefetch(callee, false, true); | |
3367 case vmIntrinsics::_prefetchReadStatic : return append_unsafe_prefetch(callee, true, false); | |
3368 case vmIntrinsics::_prefetchWriteStatic : return append_unsafe_prefetch(callee, true, true); | |
3369 | |
3370 case vmIntrinsics::_checkIndex : | |
3371 if (!InlineNIOCheckIndex) return false; | |
3372 preserves_state = true; | |
3373 break; | |
3374 case vmIntrinsics::_putOrderedObject : return append_unsafe_put_obj(callee, T_OBJECT, true); | |
3375 case vmIntrinsics::_putOrderedInt : return append_unsafe_put_obj(callee, T_INT, true); | |
3376 case vmIntrinsics::_putOrderedLong : return append_unsafe_put_obj(callee, T_LONG, true); | |
3377 | |
3378 case vmIntrinsics::_compareAndSwapLong: | |
3379 if (!VM_Version::supports_cx8()) return false; | |
3380 // fall through | |
3381 case vmIntrinsics::_compareAndSwapInt: | |
3382 case vmIntrinsics::_compareAndSwapObject: | |
3383 append_unsafe_CAS(callee); | |
3384 return true; | |
3385 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3386 case vmIntrinsics::_getAndAddInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3387 if (!VM_Version::supports_atomic_getadd4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3388 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3389 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3390 return append_unsafe_get_and_set_obj(callee, true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3391 case vmIntrinsics::_getAndAddLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3392 if (!VM_Version::supports_atomic_getadd8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3393 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3394 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3395 return append_unsafe_get_and_set_obj(callee, true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3396 case vmIntrinsics::_getAndSetInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3397 if (!VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3398 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3399 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3400 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3401 case vmIntrinsics::_getAndSetLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3402 if (!VM_Version::supports_atomic_getset8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3403 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3404 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3405 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3406 case vmIntrinsics::_getAndSetObject: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3407 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3408 if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3409 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3410 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3411 if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3412 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3413 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3414 #else |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3415 if (!VM_Version::supports_atomic_getset4()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3416 return false; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3417 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3418 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3419 return append_unsafe_get_and_set_obj(callee, false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3420 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3421 case vmIntrinsics::_Reference_get: |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6267
diff
changeset
|
3422 // 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
|
3423 // 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
|
3424 // 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
|
3425 // since GC can change its value. |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3426 preserves_state = true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3427 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
3428 |
0 | 3429 default : return false; // do not inline |
3430 } | |
3431 // create intrinsic node | |
3432 const bool has_receiver = !callee->is_static(); | |
3433 ValueType* result_type = as_ValueType(callee->return_type()); | |
1819 | 3434 ValueStack* state_before = copy_state_for_exception(); |
0 | 3435 |
3436 Values* args = state()->pop_arguments(callee->arg_size()); | |
1783 | 3437 |
3438 if (is_profiling()) { | |
0 | 3439 // Don't profile in the special case where the root method |
3440 // is the intrinsic | |
3441 if (callee != method()) { | |
1783 | 3442 // Note that we'd collect profile data in this method if we wanted it. |
3443 compilation()->set_would_profile(true); | |
3444 if (profile_calls()) { | |
3445 Value recv = NULL; | |
3446 if (has_receiver) { | |
3447 recv = args->at(0); | |
3448 null_check(recv); | |
3449 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3450 profile_call(callee, recv, NULL); |
0 | 3451 } |
3452 } | |
3453 } | |
3454 | |
1819 | 3455 Intrinsic* result = new Intrinsic(result_type, id, args, has_receiver, state_before, |
0 | 3456 preserves_state, cantrap); |
3457 // append instruction & push result | |
3458 Value value = append_split(result); | |
3459 if (result_type != voidType) push(result_type, value); | |
3460 | |
3461 // done | |
3462 return true; | |
3463 } | |
3464 | |
3465 | |
3466 bool GraphBuilder::try_inline_jsr(int jsr_dest_bci) { | |
3467 // Introduce a new callee continuation point - all Ret instructions | |
3468 // will be replaced with Gotos to this point. | |
3469 BlockBegin* cont = block_at(next_bci()); | |
3470 assert(cont != NULL, "continuation must exist (BlockListBuilder starts a new block after a jsr"); | |
3471 | |
3472 // Note: can not assign state to continuation yet, as we have to | |
3473 // pick up the state from the Ret instructions. | |
3474 | |
3475 // Push callee scope | |
3476 push_scope_for_jsr(cont, jsr_dest_bci); | |
3477 | |
3478 // Temporarily set up bytecode stream so we can append instructions | |
3479 // (only using the bci of this stream) | |
3480 scope_data()->set_stream(scope_data()->parent()->stream()); | |
3481 | |
3482 BlockBegin* jsr_start_block = block_at(jsr_dest_bci); | |
3483 assert(jsr_start_block != NULL, "jsr start block must exist"); | |
3484 assert(!jsr_start_block->is_set(BlockBegin::was_visited_flag), "should not have visited jsr yet"); | |
3485 Goto* goto_sub = new Goto(jsr_start_block, false); | |
3486 // Must copy state to avoid wrong sharing when parsing bytecodes | |
3487 assert(jsr_start_block->state() == NULL, "should have fresh jsr starting block"); | |
1819 | 3488 jsr_start_block->set_state(copy_state_before_with_bci(jsr_dest_bci)); |
0 | 3489 append(goto_sub); |
3490 _block->set_end(goto_sub); | |
3491 _last = _block = jsr_start_block; | |
3492 | |
3493 // Clear out bytecode stream | |
3494 scope_data()->set_stream(NULL); | |
3495 | |
3496 scope_data()->add_to_work_list(jsr_start_block); | |
3497 | |
3498 // Ready to resume parsing in subroutine | |
3499 iterate_all_blocks(); | |
3500 | |
3501 // If we bailed out during parsing, return immediately (this is bad news) | |
3502 CHECK_BAILOUT_(false); | |
3503 | |
3504 // Detect whether the continuation can actually be reached. If not, | |
3505 // it has not had state set by the join() operations in | |
3506 // iterate_bytecodes_for_block()/ret() and we should not touch the | |
3507 // iteration state. The calling activation of | |
3508 // iterate_bytecodes_for_block will then complete normally. | |
3509 if (cont->state() != NULL) { | |
3510 if (!cont->is_set(BlockBegin::was_visited_flag)) { | |
3511 // add continuation to work list instead of parsing it immediately | |
3512 scope_data()->parent()->add_to_work_list(cont); | |
3513 } | |
3514 } | |
3515 | |
3516 assert(jsr_continuation() == cont, "continuation must not have changed"); | |
3517 assert(!jsr_continuation()->is_set(BlockBegin::was_visited_flag) || | |
3518 jsr_continuation()->is_set(BlockBegin::parser_loop_header_flag), | |
3519 "continuation can only be visited in case of backward branches"); | |
3520 assert(_last && _last->as_BlockEnd(), "block must have end"); | |
3521 | |
3522 // continuation is in work list, so end iteration of current block | |
3523 _skip_block = true; | |
3524 pop_scope_for_jsr(); | |
3525 | |
3526 return true; | |
3527 } | |
3528 | |
3529 | |
3530 // Inline the entry of a synchronized method as a monitor enter and | |
3531 // register the exception handler which releases the monitor if an | |
3532 // exception is thrown within the callee. Note that the monitor enter | |
3533 // cannot throw an exception itself, because the receiver is | |
3534 // guaranteed to be non-null by the explicit null check at the | |
3535 // beginning of inlining. | |
3536 void GraphBuilder::inline_sync_entry(Value lock, BlockBegin* sync_handler) { | |
3537 assert(lock != NULL && sync_handler != NULL, "lock or handler missing"); | |
3538 | |
3539 monitorenter(lock, SynchronizationEntryBCI); | |
3540 assert(_last->as_MonitorEnter() != NULL, "monitor enter expected"); | |
3541 _last->set_needs_null_check(false); | |
3542 | |
3543 sync_handler->set(BlockBegin::exception_entry_flag); | |
3544 sync_handler->set(BlockBegin::is_on_work_list_flag); | |
3545 | |
3546 ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); | |
3547 XHandler* h = new XHandler(desc); | |
3548 h->set_entry_block(sync_handler); | |
3549 scope_data()->xhandlers()->append(h); | |
3550 scope_data()->set_has_handler(); | |
3551 } | |
3552 | |
3553 | |
3554 // If an exception is thrown and not handled within an inlined | |
3555 // synchronized method, the monitor must be released before the | |
3556 // exception is rethrown in the outer scope. Generate the appropriate | |
3557 // instructions here. | |
3558 void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler) { | |
3559 BlockBegin* orig_block = _block; | |
3560 ValueStack* orig_state = _state; | |
3561 Instruction* orig_last = _last; | |
3562 _last = _block = sync_handler; | |
3563 _state = sync_handler->state()->copy(); | |
3564 | |
3565 assert(sync_handler != NULL, "handler missing"); | |
3566 assert(!sync_handler->is_set(BlockBegin::was_visited_flag), "is visited here"); | |
3567 | |
3568 assert(lock != NULL || default_handler, "lock or handler missing"); | |
3569 | |
3570 XHandler* h = scope_data()->xhandlers()->remove_last(); | |
3571 assert(h->entry_block() == sync_handler, "corrupt list of handlers"); | |
3572 | |
3573 block()->set(BlockBegin::was_visited_flag); | |
3574 Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI); | |
3575 assert(exception->is_pinned(), "must be"); | |
3576 | |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3577 int bci = SynchronizationEntryBCI; |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3578 if (compilation()->env()->dtrace_method_probes()) { |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3579 // 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
|
3580 // 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
|
3581 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
3582 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
|
3583 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
|
3584 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3585 |
0 | 3586 if (lock) { |
3587 assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing"); | |
1819 | 3588 if (!lock->is_linked()) { |
2318
6f3746e69a78
7021603: crash in fill_sync_handler with ExtendedDTrace probes
never
parents:
2167
diff
changeset
|
3589 lock = append_with_bci(lock, bci); |
0 | 3590 } |
3591 | |
3592 // 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
|
3593 monitorexit(lock, bci); |
0 | 3594 |
3595 // exit the context of the synchronized method | |
3596 if (!default_handler) { | |
3597 pop_scope(); | |
1819 | 3598 bci = _state->caller_state()->bci(); |
3599 _state = _state->caller_state()->copy_for_parsing(); | |
0 | 3600 } |
3601 } | |
3602 | |
3603 // perform the throw as if at the the call site | |
3604 apush(exception); | |
3605 throw_op(bci); | |
3606 | |
3607 BlockEnd* end = last()->as_BlockEnd(); | |
3608 block()->set_end(end); | |
3609 | |
3610 _block = orig_block; | |
3611 _state = orig_state; | |
3612 _last = orig_last; | |
3613 } | |
3614 | |
3615 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3616 bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecodes::Code bc, Value receiver) { |
0 | 3617 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
|
3618 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { |
2c359f27615c
7057120: Tiered: Allow C1 to inline methods with loops
iveresov
parents:
3255
diff
changeset
|
3619 INLINE_BAILOUT("inlining prohibited by policy"); |
1783 | 3620 } |
0 | 3621 // first perform tests of things it's not possible to inline |
3622 if (callee->has_exception_handlers() && | |
3623 !InlineMethodsWithExceptionHandlers) INLINE_BAILOUT("callee has exception handlers"); | |
3624 if (callee->is_synchronized() && | |
3625 !InlineSynchronizedMethods ) INLINE_BAILOUT("callee is synchronized"); | |
3626 if (!callee->holder()->is_initialized()) INLINE_BAILOUT("callee's klass not initialized yet"); | |
3627 if (!callee->has_balanced_monitors()) INLINE_BAILOUT("callee's monitors do not match"); | |
3628 | |
3629 // Proper inlining of methods with jsrs requires a little more work. | |
3630 if (callee->has_jsrs() ) INLINE_BAILOUT("jsrs not handled properly by inliner yet"); | |
3631 | |
3632 // When SSE2 is used on intel, then no special handling is needed | |
3633 // for strictfp because the enum-constant is fixed at compile time, | |
3634 // the check for UseSSE2 is needed here | |
3635 if (strict_fp_requires_explicit_rounding && UseSSE < 2 && method()->is_strict() != callee->is_strict()) { | |
3636 INLINE_BAILOUT("caller and callee have different strict fp requirements"); | |
3637 } | |
3638 | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3639 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
|
3640 INLINE_BAILOUT("mdo allocation failed"); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3641 } |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3642 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3643 // now perform tests that are based on flag settings |
6222
6d8f36bcef55
6711908: JVM needs direct access to some annotations
jrose
parents:
6143
diff
changeset
|
3644 if (callee->force_inline() || callee->should_inline()) { |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3645 // ignore heuristic controls on inlining |
6222
6d8f36bcef55
6711908: JVM needs direct access to some annotations
jrose
parents:
6143
diff
changeset
|
3646 if (callee->force_inline()) |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3647 print_inlining(callee, "force inline by annotation"); |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3648 } else { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3649 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
|
3650 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
|
3651 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
|
3652 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3653 // 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
|
3654 if (callee->name() == ciSymbol::object_initializer_name() && |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3655 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
|
3656 // Throwable constructor call |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3657 IRScope* top = scope(); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3658 while (top->caller() != NULL) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3659 top = top->caller(); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3660 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3661 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
|
3662 INLINE_BAILOUT("don't inline Throwable constructors"); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3663 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3664 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3665 |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3666 if (compilation()->env()->num_inlined_bytecodes() > DesiredMethodLimit) { |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3667 INLINE_BAILOUT("total inlining greater than DesiredMethodLimit"); |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3668 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3669 // printing |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3670 print_inlining(callee, ""); |
3844
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3671 } |
ce3e1d4dc416
7060619: C1 should respect inline and dontinline directives from CompilerOracle
never
parents:
3791
diff
changeset
|
3672 |
0 | 3673 // NOTE: Bailouts from this point on, which occur at the |
3674 // GraphBuilder level, do not cause bailout just of the inlining but | |
3675 // in fact of the entire compilation. | |
3676 | |
3677 BlockBegin* orig_block = block(); | |
3678 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3679 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
|
3680 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
|
3681 |
0 | 3682 const int args_base = state()->stack_size() - callee->arg_size(); |
3683 assert(args_base >= 0, "stack underflow during inlining"); | |
3684 | |
3685 // Insert null check if necessary | |
3686 Value recv = NULL; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3687 if (has_receiver) { |
0 | 3688 // note: null check must happen even if first instruction of callee does |
3689 // an implicit null check since the callee is in a different scope | |
3690 // and we must make sure exception handling does the right thing | |
3691 assert(!callee->is_static(), "callee must not be static"); | |
3692 assert(callee->arg_size() > 0, "must have at least a receiver"); | |
3693 recv = state()->stack_at(args_base); | |
3694 null_check(recv); | |
3695 } | |
3696 | |
1783 | 3697 if (is_profiling()) { |
3698 // Note that we'd collect profile data in this method if we wanted it. | |
3699 // this may be redundant here... | |
3700 compilation()->set_would_profile(true); | |
3701 | |
3702 if (profile_calls()) { | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3703 profile_call(callee, recv, holder_known ? callee->holder() : NULL); |
1783 | 3704 } |
0 | 3705 } |
3706 | |
3707 // Introduce a new callee continuation point - if the callee has | |
3708 // more than one return instruction or the return does not allow | |
3709 // fall-through of control flow, all return instructions of the | |
3710 // callee will need to be replaced by Goto's pointing to this | |
3711 // continuation point. | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3712 BlockBegin* cont = block_at(next_bci()); |
0 | 3713 bool continuation_existed = true; |
3714 if (cont == NULL) { | |
3715 cont = new BlockBegin(next_bci()); | |
3716 // low number so that continuation gets parsed as early as possible | |
3717 cont->set_depth_first_number(0); | |
3718 #ifndef PRODUCT | |
3719 if (PrintInitialBlockList) { | |
3720 tty->print_cr("CFG: created block %d (bci %d) as continuation for inline at bci %d", | |
3721 cont->block_id(), cont->bci(), bci()); | |
3722 } | |
3723 #endif | |
3724 continuation_existed = false; | |
3725 } | |
3726 // Record number of predecessors of continuation block before | |
3727 // inlining, to detect if inlined method has edges to its | |
3728 // continuation after inlining. | |
3729 int continuation_preds = cont->number_of_preds(); | |
3730 | |
3731 // Push callee scope | |
3732 push_scope(callee, cont); | |
3733 | |
3734 // the BlockListBuilder for the callee could have bailed out | |
3735 CHECK_BAILOUT_(false); | |
3736 | |
3737 // Temporarily set up bytecode stream so we can append instructions | |
3738 // (only using the bci of this stream) | |
3739 scope_data()->set_stream(scope_data()->parent()->stream()); | |
3740 | |
3741 // Pass parameters into callee state: add assignments | |
3742 // note: this will also ensure that all arguments are computed before being passed | |
3743 ValueStack* callee_state = state(); | |
1819 | 3744 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
|
3745 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
|
3746 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
|
3747 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
|
3748 store_local(callee_state, arg, arg_no); |
0 | 3749 } |
3750 | |
3751 // Remove args from stack. | |
3752 // Note that we preserve locals state in case we can use it later | |
3753 // (see use of pop_scope() below) | |
3754 caller_state->truncate_stack(args_base); | |
1819 | 3755 assert(callee_state->stack_size() == 0, "callee stack must be empty"); |
0 | 3756 |
3757 Value lock; | |
3758 BlockBegin* sync_handler; | |
3759 | |
3760 // Inline the locking of the receiver if the callee is synchronized | |
3761 if (callee->is_synchronized()) { | |
3762 lock = callee->is_static() ? append(new Constant(new InstanceConstant(callee->holder()->java_mirror()))) | |
3763 : state()->local_at(0); | |
1819 | 3764 sync_handler = new BlockBegin(SynchronizationEntryBCI); |
0 | 3765 inline_sync_entry(lock, sync_handler); |
3766 } | |
3767 | |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3768 if (compilation()->env()->dtrace_method_probes()) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2007
diff
changeset
|
3769 Values* args = new Values(1); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6634
diff
changeset
|
3770 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
|
3771 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
|
3772 } |
0 | 3773 |
4116
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3774 if (profile_inlined_calls()) { |
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3775 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
|
3776 } |
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
3777 |
0 | 3778 BlockBegin* callee_start_block = block_at(0); |
3779 if (callee_start_block != NULL) { | |
3780 assert(callee_start_block->is_set(BlockBegin::parser_loop_header_flag), "must be loop header"); | |
3781 Goto* goto_callee = new Goto(callee_start_block, false); | |
3782 // The state for this goto is in the scope of the callee, so use | |
3783 // the entry bci for the callee instead of the call site bci. | |
3784 append_with_bci(goto_callee, 0); | |
3785 _block->set_end(goto_callee); | |
3786 callee_start_block->merge(callee_state); | |
3787 | |
3788 _last = _block = callee_start_block; | |
3789 | |
3790 scope_data()->add_to_work_list(callee_start_block); | |
3791 } | |
3792 | |
3793 // Clear out bytecode stream | |
3794 scope_data()->set_stream(NULL); | |
3795 | |
3796 // Ready to resume parsing in callee (either in the same block we | |
3797 // were in before or in the callee's start block) | |
3798 iterate_all_blocks(callee_start_block == NULL); | |
3799 | |
3800 // If we bailed out during parsing, return immediately (this is bad news) | |
3801 if (bailed_out()) return false; | |
3802 | |
3803 // iterate_all_blocks theoretically traverses in random order; in | |
3804 // practice, we have only traversed the continuation if we are | |
3805 // inlining into a subroutine | |
3806 assert(continuation_existed || | |
3807 !continuation()->is_set(BlockBegin::was_visited_flag), | |
3808 "continuation should not have been parsed yet if we created it"); | |
3809 | |
3810 // If we bailed out during parsing, return immediately (this is bad news) | |
3811 CHECK_BAILOUT_(false); | |
3812 | |
3813 // At this point we are almost ready to return and resume parsing of | |
3814 // the caller back in the GraphBuilder. The only thing we want to do | |
3815 // first is an optimization: during parsing of the callee we | |
3816 // generated at least one Goto to the continuation block. If we | |
3817 // generated exactly one, and if the inlined method spanned exactly | |
3818 // one block (and we didn't have to Goto its entry), then we snip | |
3819 // off the Goto to the continuation, allowing control to fall | |
3820 // through back into the caller block and effectively performing | |
3821 // block merging. This allows load elimination and CSE to take place | |
3822 // across multiple callee scopes if they are relatively simple, and | |
3823 // 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
|
3824 if (num_returns() == 1 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3825 && block() == orig_block |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3826 && block() == inline_cleanup_block()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3827 _last = inline_cleanup_return_prev(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3828 _state = inline_cleanup_state(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3829 } 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
|
3830 // 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
|
3831 // 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
|
3832 // with instructions! |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3833 assert(cont == continuation(), ""); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3834 assert(_last && _last->as_BlockEnd(), ""); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3835 _skip_block = true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3836 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3837 // 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
|
3838 // 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
|
3839 // 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
|
3840 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
|
3841 // add continuation to work list instead of parsing it immediately |
0 | 3842 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
|
3843 scope_data()->parent()->add_to_work_list(continuation()); |
0 | 3844 _skip_block = true; |
3845 } | |
3846 } | |
3847 | |
3848 // Fill the exception handler for synchronized methods with instructions | |
3849 if (callee->is_synchronized() && sync_handler->state() != NULL) { | |
3850 fill_sync_handler(lock, sync_handler); | |
3851 } else { | |
3852 pop_scope(); | |
3853 } | |
3854 | |
3855 compilation()->notice_inlined_method(callee); | |
3856 | |
3857 return true; | |
3858 } | |
3859 | |
3860 | |
6634
7f813940ac35
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
twisti
parents:
6616
diff
changeset
|
3861 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
|
3862 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
|
3863 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
|
3864 switch (iid) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3865 case vmIntrinsics::_invokeBasic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3866 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3867 // get MethodHandle receiver |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3868 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
|
3869 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
|
3870 if (type->is_constant()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3871 ciMethod* target = type->as_ObjectType()->constant_value()->as_method_handle()->get_vmtarget(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3872 guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3873 Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3874 if (try_inline(target, /*holder_known*/ true, bc)) { |
4870
2f5980b127e3
7132180: JSR 292: C1 JVM crash with ClassValue/MethodHandle
twisti
parents:
4116
diff
changeset
|
3875 return true; |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3876 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3877 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3878 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
|
3879 } |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3880 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3881 break; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3882 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3883 case vmIntrinsics::_linkToVirtual: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3884 case vmIntrinsics::_linkToStatic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3885 case vmIntrinsics::_linkToSpecial: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3886 case vmIntrinsics::_linkToInterface: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3887 { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3888 // pop MemberName argument |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3889 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
|
3890 ValueType* type = apop()->type(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3891 if (type->is_constant()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3892 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
|
3893 // 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
|
3894 // a better target. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3895 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
|
3896 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
|
3897 return true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3898 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3899 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3900 ciSignature* signature = target->signature(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3901 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
|
3902 // Cast receiver to its type. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3903 if (!target->is_static()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3904 ciKlass* tk = signature->accessing_klass(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3905 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
|
3906 if (obj->exact_type() == NULL && |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3907 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
|
3908 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
|
3909 append(c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3910 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
|
3911 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3912 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3913 // 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
|
3914 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
|
3915 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
|
3916 if (t->is_klass()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3917 ciKlass* tk = t->as_klass(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3918 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
|
3919 if (obj->exact_type() == NULL && |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3920 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
|
3921 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
|
3922 append(c); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3923 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
|
3924 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3925 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3926 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
|
3927 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3928 Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3929 if (try_inline(target, /*holder_known*/ true, bc)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3930 return true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3931 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3932 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3933 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3934 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
|
3935 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3936 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3937 break; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3938 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3939 default: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3940 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
|
3941 break; |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3942 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
3943 set_state(state_before); |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3944 return false; |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3945 } |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3946 |
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3897
diff
changeset
|
3947 |
0 | 3948 void GraphBuilder::inline_bailout(const char* msg) { |
3949 assert(msg != NULL, "inline bailout msg must exist"); | |
3950 _inline_bailout_msg = msg; | |
3951 } | |
3952 | |
3953 | |
3954 void GraphBuilder::clear_inline_bailout() { | |
3955 _inline_bailout_msg = NULL; | |
3956 } | |
3957 | |
3958 | |
3959 void GraphBuilder::push_root_scope(IRScope* scope, BlockList* bci2block, BlockBegin* start) { | |
3960 ScopeData* data = new ScopeData(NULL); | |
3961 data->set_scope(scope); | |
3962 data->set_bci2block(bci2block); | |
3963 _scope_data = data; | |
3964 _block = start; | |
3965 } | |
3966 | |
3967 | |
3968 void GraphBuilder::push_scope(ciMethod* callee, BlockBegin* continuation) { | |
3969 IRScope* callee_scope = new IRScope(compilation(), scope(), bci(), callee, -1, false); | |
3970 scope()->add_callee(callee_scope); | |
3971 | |
3972 BlockListBuilder blb(compilation(), callee_scope, -1); | |
3973 CHECK_BAILOUT(); | |
3974 | |
3975 if (!blb.bci2block()->at(0)->is_set(BlockBegin::parser_loop_header_flag)) { | |
3976 // this scope can be inlined directly into the caller so remove | |
3977 // the block at bci 0. | |
3978 blb.bci2block()->at_put(0, NULL); | |
3979 } | |
3980 | |
1819 | 3981 set_state(new ValueStack(callee_scope, state()->copy(ValueStack::CallerState, bci()))); |
0 | 3982 |
3983 ScopeData* data = new ScopeData(scope_data()); | |
3984 data->set_scope(callee_scope); | |
3985 data->set_bci2block(blb.bci2block()); | |
3986 data->set_continuation(continuation); | |
3987 _scope_data = data; | |
3988 } | |
3989 | |
3990 | |
3991 void GraphBuilder::push_scope_for_jsr(BlockBegin* jsr_continuation, int jsr_dest_bci) { | |
3992 ScopeData* data = new ScopeData(scope_data()); | |
3993 data->set_parsing_jsr(); | |
3994 data->set_jsr_entry_bci(jsr_dest_bci); | |
3995 data->set_jsr_return_address_local(-1); | |
3996 // Must clone bci2block list as we will be mutating it in order to | |
3997 // properly clone all blocks in jsr region as well as exception | |
3998 // handlers containing rets | |
3999 BlockList* new_bci2block = new BlockList(bci2block()->length()); | |
4000 new_bci2block->push_all(bci2block()); | |
4001 data->set_bci2block(new_bci2block); | |
4002 data->set_scope(scope()); | |
4003 data->setup_jsr_xhandlers(); | |
4004 data->set_continuation(continuation()); | |
4005 data->set_jsr_continuation(jsr_continuation); | |
4006 _scope_data = data; | |
4007 } | |
4008 | |
4009 | |
4010 void GraphBuilder::pop_scope() { | |
4011 int number_of_locks = scope()->number_of_locks(); | |
4012 _scope_data = scope_data()->parent(); | |
4013 // accumulate minimum number of monitor slots to be reserved | |
4014 scope()->set_min_number_of_locks(number_of_locks); | |
4015 } | |
4016 | |
4017 | |
4018 void GraphBuilder::pop_scope_for_jsr() { | |
4019 _scope_data = scope_data()->parent(); | |
4020 } | |
4021 | |
4022 bool GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) { | |
4023 if (InlineUnsafeOps) { | |
4024 Values* args = state()->pop_arguments(callee->arg_size()); | |
4025 null_check(args->at(0)); | |
4026 Instruction* offset = args->at(2); | |
4027 #ifndef _LP64 | |
4028 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4029 #endif | |
4030 Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile)); | |
4031 push(op->type(), op); | |
4032 compilation()->set_has_unsafe_access(true); | |
4033 } | |
4034 return InlineUnsafeOps; | |
4035 } | |
4036 | |
4037 | |
4038 bool GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile) { | |
4039 if (InlineUnsafeOps) { | |
4040 Values* args = state()->pop_arguments(callee->arg_size()); | |
4041 null_check(args->at(0)); | |
4042 Instruction* offset = args->at(2); | |
4043 #ifndef _LP64 | |
4044 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4045 #endif | |
4046 Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); | |
4047 compilation()->set_has_unsafe_access(true); | |
4048 kill_all(); | |
4049 } | |
4050 return InlineUnsafeOps; | |
4051 } | |
4052 | |
4053 | |
4054 bool GraphBuilder::append_unsafe_get_raw(ciMethod* callee, BasicType t) { | |
4055 if (InlineUnsafeOps) { | |
4056 Values* args = state()->pop_arguments(callee->arg_size()); | |
4057 null_check(args->at(0)); | |
4058 Instruction* op = append(new UnsafeGetRaw(t, args->at(1), false)); | |
4059 push(op->type(), op); | |
4060 compilation()->set_has_unsafe_access(true); | |
4061 } | |
4062 return InlineUnsafeOps; | |
4063 } | |
4064 | |
4065 | |
4066 bool GraphBuilder::append_unsafe_put_raw(ciMethod* callee, BasicType t) { | |
4067 if (InlineUnsafeOps) { | |
4068 Values* args = state()->pop_arguments(callee->arg_size()); | |
4069 null_check(args->at(0)); | |
4070 Instruction* op = append(new UnsafePutRaw(t, args->at(1), args->at(2))); | |
4071 compilation()->set_has_unsafe_access(true); | |
4072 } | |
4073 return InlineUnsafeOps; | |
4074 } | |
4075 | |
4076 | |
4077 bool GraphBuilder::append_unsafe_prefetch(ciMethod* callee, bool is_static, bool is_store) { | |
4078 if (InlineUnsafeOps) { | |
4079 Values* args = state()->pop_arguments(callee->arg_size()); | |
4080 int obj_arg_index = 1; // Assume non-static case | |
4081 if (is_static) { | |
4082 obj_arg_index = 0; | |
4083 } else { | |
4084 null_check(args->at(0)); | |
4085 } | |
4086 Instruction* offset = args->at(obj_arg_index + 1); | |
4087 #ifndef _LP64 | |
4088 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4089 #endif | |
4090 Instruction* op = is_store ? append(new UnsafePrefetchWrite(args->at(obj_arg_index), offset)) | |
4091 : append(new UnsafePrefetchRead (args->at(obj_arg_index), offset)); | |
4092 compilation()->set_has_unsafe_access(true); | |
4093 } | |
4094 return InlineUnsafeOps; | |
4095 } | |
4096 | |
4097 | |
4098 void GraphBuilder::append_unsafe_CAS(ciMethod* callee) { | |
1819 | 4099 ValueStack* state_before = copy_state_for_exception(); |
0 | 4100 ValueType* result_type = as_ValueType(callee->return_type()); |
4101 assert(result_type->is_int(), "int result"); | |
4102 Values* args = state()->pop_arguments(callee->arg_size()); | |
4103 | |
4104 // Pop off some args to speically handle, then push back | |
4105 Value newval = args->pop(); | |
4106 Value cmpval = args->pop(); | |
4107 Value offset = args->pop(); | |
4108 Value src = args->pop(); | |
4109 Value unsafe_obj = args->pop(); | |
4110 | |
4111 // Separately handle the unsafe arg. It is not needed for code | |
4112 // generation, but must be null checked | |
4113 null_check(unsafe_obj); | |
4114 | |
4115 #ifndef _LP64 | |
4116 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); | |
4117 #endif | |
4118 | |
4119 args->push(src); | |
4120 args->push(offset); | |
4121 args->push(cmpval); | |
4122 args->push(newval); | |
4123 | |
4124 // An unsafe CAS can alias with other field accesses, but we don't | |
4125 // know which ones so mark the state as no preserved. This will | |
4126 // cause CSE to invalidate memory across it. | |
4127 bool preserves_state = false; | |
1819 | 4128 Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(), args, false, state_before, preserves_state); |
0 | 4129 append_split(result); |
4130 push(result_type, result); | |
4131 compilation()->set_has_unsafe_access(true); | |
4132 } | |
4133 | |
4134 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4135 void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4136 if (!PrintInlining) return; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4137 assert(msg != NULL, "must be"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4138 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
|
4139 if (success && CIPrintMethodCodes) { |
0 | 4140 callee->print_codes(); |
4141 } | |
4142 } | |
4143 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4144 bool GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4145 if (InlineUnsafeOps) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4146 Values* args = state()->pop_arguments(callee->arg_size()); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4147 BasicType t = callee->return_type()->basic_type(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4148 null_check(args->at(0)); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4149 Instruction* offset = args->at(2); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4150 #ifndef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4151 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4152 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4153 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
|
4154 compilation()->set_has_unsafe_access(true); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4155 kill_all(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4156 push(op->type(), op); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4157 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4158 return InlineUnsafeOps; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
4159 } |
0 | 4160 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4161 #ifndef PRODUCT |
0 | 4162 void GraphBuilder::print_stats() { |
4163 vmap()->print(); | |
4164 } | |
4165 #endif // PRODUCT | |
4166 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4167 void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6222
diff
changeset
|
4168 append(new ProfileCall(method(), bci(), callee, recv, known_holder)); |
0 | 4169 } |
4170 | |
1825 | 4171 void GraphBuilder::profile_invocation(ciMethod* callee, ValueStack* state) { |
4172 append(new ProfileInvoke(callee, state)); | |
0 | 4173 } |