Mercurial > hg > truffle
comparison src/share/vm/shark/sharkInliner.cpp @ 1692:d2ede61b7a12
6976186: integrate Shark HotSpot changes
Summary: Shark is a JIT compiler for Zero that uses the LLVM compiler infrastructure.
Reviewed-by: kvn, twisti
Contributed-by: Gary Benson <gbenson@redhat.com>
author | twisti |
---|---|
date | Wed, 11 Aug 2010 05:51:21 -0700 |
parents | |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1691:4a665be40fd3 | 1692:d2ede61b7a12 |
---|---|
1 /* | |
2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. | |
3 * Copyright 2009 Red Hat, Inc. | |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 * | |
6 * This code is free software; you can redistribute it and/or modify it | |
7 * under the terms of the GNU General Public License version 2 only, as | |
8 * published by the Free Software Foundation. | |
9 * | |
10 * This code is distributed in the hope that it will be useful, but WITHOUT | |
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 * version 2 for more details (a copy is included in the LICENSE file that | |
14 * accompanied this code). | |
15 * | |
16 * You should have received a copy of the GNU General Public License version | |
17 * 2 along with this work; if not, write to the Free Software Foundation, | |
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 * | |
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
21 * or visit www.oracle.com if you need additional information or have any | |
22 * questions. | |
23 * | |
24 */ | |
25 | |
26 #include "incls/_precompiled.incl" | |
27 #include "incls/_sharkInliner.cpp.incl" | |
28 | |
29 using namespace llvm; | |
30 | |
31 class SharkInlineBlock : public SharkBlock { | |
32 public: | |
33 SharkInlineBlock(ciMethod* target, SharkState* state) | |
34 : SharkBlock(state, target), | |
35 _outer_state(state), | |
36 _entry_state(new SharkState(this)) { | |
37 for (int i = target->max_locals() - 1; i >= 0; i--) { | |
38 SharkValue *value = NULL; | |
39 if (i < target->arg_size()) | |
40 value = outer_state()->pop(); | |
41 entry_state()->set_local(i, value); | |
42 } | |
43 } | |
44 | |
45 private: | |
46 SharkState* _outer_state; | |
47 SharkState* _entry_state; | |
48 | |
49 private: | |
50 SharkState* outer_state() { | |
51 return _outer_state; | |
52 } | |
53 SharkState* entry_state() { | |
54 return _entry_state; | |
55 } | |
56 | |
57 public: | |
58 void emit_IR() { | |
59 parse_bytecode(0, target()->code_size()); | |
60 } | |
61 | |
62 private: | |
63 void do_return(BasicType type) { | |
64 if (type != T_VOID) { | |
65 SharkValue *result = pop_result(type); | |
66 outer_state()->push(result); | |
67 if (result->is_two_word()) | |
68 outer_state()->push(NULL); | |
69 } | |
70 } | |
71 }; | |
72 | |
73 class SharkInlinerHelper : public StackObj { | |
74 public: | |
75 SharkInlinerHelper(ciMethod* target, SharkState* entry_state) | |
76 : _target(target), | |
77 _entry_state(entry_state), | |
78 _iter(target) {} | |
79 | |
80 private: | |
81 ciBytecodeStream _iter; | |
82 SharkState* _entry_state; | |
83 ciMethod* _target; | |
84 | |
85 public: | |
86 ciBytecodeStream* iter() { | |
87 return &_iter; | |
88 } | |
89 SharkState* entry_state() const { | |
90 return _entry_state; | |
91 } | |
92 ciMethod* target() const { | |
93 return _target; | |
94 } | |
95 | |
96 public: | |
97 Bytecodes::Code bc() { | |
98 return iter()->cur_bc(); | |
99 } | |
100 int max_locals() const { | |
101 return target()->max_locals(); | |
102 } | |
103 int max_stack() const { | |
104 return target()->max_stack(); | |
105 } | |
106 | |
107 // Inlinability check | |
108 public: | |
109 bool is_inlinable(); | |
110 | |
111 private: | |
112 void initialize_for_check(); | |
113 | |
114 bool do_getstatic() { | |
115 return do_field_access(true, false); | |
116 } | |
117 bool do_getfield() { | |
118 return do_field_access(true, true); | |
119 } | |
120 bool do_putfield() { | |
121 return do_field_access(false, true); | |
122 } | |
123 bool do_field_access(bool is_get, bool is_field); | |
124 | |
125 // Local variables for inlinability check | |
126 private: | |
127 bool* _locals; | |
128 | |
129 public: | |
130 bool* local_addr(int index) const { | |
131 assert(index >= 0 && index < max_locals(), "bad local variable index"); | |
132 return &_locals[index]; | |
133 } | |
134 bool local(int index) const { | |
135 return *local_addr(index); | |
136 } | |
137 void set_local(int index, bool value) { | |
138 *local_addr(index) = value; | |
139 } | |
140 | |
141 // Expression stack for inlinability check | |
142 private: | |
143 bool* _stack; | |
144 bool* _sp; | |
145 | |
146 public: | |
147 int stack_depth() const { | |
148 return _sp - _stack; | |
149 } | |
150 bool* stack_addr(int slot) const { | |
151 assert(slot >= 0 && slot < stack_depth(), "bad stack slot"); | |
152 return &_sp[-(slot + 1)]; | |
153 } | |
154 void push(bool value) { | |
155 assert(stack_depth() < max_stack(), "stack overrun"); | |
156 *(_sp++) = value; | |
157 } | |
158 bool pop() { | |
159 assert(stack_depth() > 0, "stack underrun"); | |
160 return *(--_sp); | |
161 } | |
162 | |
163 // Methods for two-word locals | |
164 public: | |
165 void push_pair_local(int index) { | |
166 push(local(index)); | |
167 push(local(index + 1)); | |
168 } | |
169 void pop_pair_local(int index) { | |
170 set_local(index + 1, pop()); | |
171 set_local(index, pop()); | |
172 } | |
173 | |
174 // Code generation | |
175 public: | |
176 void do_inline() { | |
177 (new SharkInlineBlock(target(), entry_state()))->emit_IR(); | |
178 } | |
179 }; | |
180 | |
181 // Quick checks so we can bail out before doing too much | |
182 bool SharkInliner::may_be_inlinable(ciMethod *target) { | |
183 // We can't inline native methods | |
184 if (target->is_native()) | |
185 return false; | |
186 | |
187 // Not much point inlining abstract ones, and in any | |
188 // case we'd need a stack frame to throw the exception | |
189 if (target->is_abstract()) | |
190 return false; | |
191 | |
192 // Don't inline anything huge | |
193 if (target->code_size() > SharkMaxInlineSize) | |
194 return false; | |
195 | |
196 // Monitors aren't allowed without a frame to put them in | |
197 if (target->is_synchronized() || target->has_monitor_bytecodes()) | |
198 return false; | |
199 | |
200 // We don't do control flow | |
201 if (target->has_exception_handlers() || target->has_jsrs()) | |
202 return false; | |
203 | |
204 // Don't try to inline constructors, as they must | |
205 // eventually call Object.<init> which we can't inline. | |
206 // Note that this catches <clinit> too, but why would | |
207 // we be compiling that? | |
208 if (target->is_initializer()) | |
209 return false; | |
210 | |
211 // Mustn't inline Object.<init> | |
212 // Should be caught by the above, but just in case... | |
213 if (target->intrinsic_id() == vmIntrinsics::_Object_init) | |
214 return false; | |
215 | |
216 return true; | |
217 } | |
218 | |
219 // Full-on detailed check, for methods that pass the quick checks | |
220 // Inlined methods have no stack frame, so we can't do anything | |
221 // that would require one. This means no safepoints (and hence | |
222 // no loops) and no VM calls. No VM calls means, amongst other | |
223 // things, that no exceptions can be created, which means no null | |
224 // checks or divide-by-zero checks are allowed. The lack of null | |
225 // checks in particular would eliminate practically everything, | |
226 // but we can get around that restriction by relying on the zero- | |
227 // check eliminator to strip the checks. To do that, we need to | |
228 // walk through the method, tracking which values are and are not | |
229 // zero-checked. | |
230 bool SharkInlinerHelper::is_inlinable() { | |
231 ResourceMark rm; | |
232 initialize_for_check(); | |
233 | |
234 SharkConstant *sc; | |
235 bool a, b, c, d; | |
236 | |
237 iter()->reset_to_bci(0); | |
238 while (iter()->next() != ciBytecodeStream::EOBC()) { | |
239 switch (bc()) { | |
240 case Bytecodes::_nop: | |
241 break; | |
242 | |
243 case Bytecodes::_aconst_null: | |
244 push(false); | |
245 break; | |
246 | |
247 case Bytecodes::_iconst_0: | |
248 push(false); | |
249 break; | |
250 case Bytecodes::_iconst_m1: | |
251 case Bytecodes::_iconst_1: | |
252 case Bytecodes::_iconst_2: | |
253 case Bytecodes::_iconst_3: | |
254 case Bytecodes::_iconst_4: | |
255 case Bytecodes::_iconst_5: | |
256 push(true); | |
257 break; | |
258 | |
259 case Bytecodes::_lconst_0: | |
260 push(false); | |
261 push(false); | |
262 break; | |
263 case Bytecodes::_lconst_1: | |
264 push(true); | |
265 push(false); | |
266 break; | |
267 | |
268 case Bytecodes::_fconst_0: | |
269 case Bytecodes::_fconst_1: | |
270 case Bytecodes::_fconst_2: | |
271 push(false); | |
272 break; | |
273 | |
274 case Bytecodes::_dconst_0: | |
275 case Bytecodes::_dconst_1: | |
276 push(false); | |
277 push(false); | |
278 break; | |
279 | |
280 case Bytecodes::_bipush: | |
281 push(iter()->get_constant_u1() != 0); | |
282 break; | |
283 case Bytecodes::_sipush: | |
284 push(iter()->get_constant_u2() != 0); | |
285 break; | |
286 | |
287 case Bytecodes::_ldc: | |
288 case Bytecodes::_ldc_w: | |
289 case Bytecodes::_ldc2_w: | |
290 sc = SharkConstant::for_ldc(iter()); | |
291 if (!sc->is_loaded()) | |
292 return false; | |
293 push(sc->is_nonzero()); | |
294 if (sc->is_two_word()) | |
295 push(false); | |
296 break; | |
297 | |
298 case Bytecodes::_iload_0: | |
299 case Bytecodes::_fload_0: | |
300 case Bytecodes::_aload_0: | |
301 push(local(0)); | |
302 break; | |
303 case Bytecodes::_lload_0: | |
304 case Bytecodes::_dload_0: | |
305 push_pair_local(0); | |
306 break; | |
307 | |
308 case Bytecodes::_iload_1: | |
309 case Bytecodes::_fload_1: | |
310 case Bytecodes::_aload_1: | |
311 push(local(1)); | |
312 break; | |
313 case Bytecodes::_lload_1: | |
314 case Bytecodes::_dload_1: | |
315 push_pair_local(1); | |
316 break; | |
317 | |
318 case Bytecodes::_iload_2: | |
319 case Bytecodes::_fload_2: | |
320 case Bytecodes::_aload_2: | |
321 push(local(2)); | |
322 break; | |
323 case Bytecodes::_lload_2: | |
324 case Bytecodes::_dload_2: | |
325 push_pair_local(2); | |
326 break; | |
327 | |
328 case Bytecodes::_iload_3: | |
329 case Bytecodes::_fload_3: | |
330 case Bytecodes::_aload_3: | |
331 push(local(3)); | |
332 break; | |
333 case Bytecodes::_lload_3: | |
334 case Bytecodes::_dload_3: | |
335 push_pair_local(3); | |
336 break; | |
337 | |
338 case Bytecodes::_iload: | |
339 case Bytecodes::_fload: | |
340 case Bytecodes::_aload: | |
341 push(local(iter()->get_index())); | |
342 break; | |
343 case Bytecodes::_lload: | |
344 case Bytecodes::_dload: | |
345 push_pair_local(iter()->get_index()); | |
346 break; | |
347 | |
348 case Bytecodes::_istore_0: | |
349 case Bytecodes::_fstore_0: | |
350 case Bytecodes::_astore_0: | |
351 set_local(0, pop()); | |
352 break; | |
353 case Bytecodes::_lstore_0: | |
354 case Bytecodes::_dstore_0: | |
355 pop_pair_local(0); | |
356 break; | |
357 | |
358 case Bytecodes::_istore_1: | |
359 case Bytecodes::_fstore_1: | |
360 case Bytecodes::_astore_1: | |
361 set_local(1, pop()); | |
362 break; | |
363 case Bytecodes::_lstore_1: | |
364 case Bytecodes::_dstore_1: | |
365 pop_pair_local(1); | |
366 break; | |
367 | |
368 case Bytecodes::_istore_2: | |
369 case Bytecodes::_fstore_2: | |
370 case Bytecodes::_astore_2: | |
371 set_local(2, pop()); | |
372 break; | |
373 case Bytecodes::_lstore_2: | |
374 case Bytecodes::_dstore_2: | |
375 pop_pair_local(2); | |
376 break; | |
377 | |
378 case Bytecodes::_istore_3: | |
379 case Bytecodes::_fstore_3: | |
380 case Bytecodes::_astore_3: | |
381 set_local(3, pop()); | |
382 break; | |
383 case Bytecodes::_lstore_3: | |
384 case Bytecodes::_dstore_3: | |
385 pop_pair_local(3); | |
386 break; | |
387 | |
388 case Bytecodes::_istore: | |
389 case Bytecodes::_fstore: | |
390 case Bytecodes::_astore: | |
391 set_local(iter()->get_index(), pop()); | |
392 break; | |
393 case Bytecodes::_lstore: | |
394 case Bytecodes::_dstore: | |
395 pop_pair_local(iter()->get_index()); | |
396 break; | |
397 | |
398 case Bytecodes::_pop: | |
399 pop(); | |
400 break; | |
401 case Bytecodes::_pop2: | |
402 pop(); | |
403 pop(); | |
404 break; | |
405 case Bytecodes::_swap: | |
406 a = pop(); | |
407 b = pop(); | |
408 push(a); | |
409 push(b); | |
410 break; | |
411 case Bytecodes::_dup: | |
412 a = pop(); | |
413 push(a); | |
414 push(a); | |
415 break; | |
416 case Bytecodes::_dup_x1: | |
417 a = pop(); | |
418 b = pop(); | |
419 push(a); | |
420 push(b); | |
421 push(a); | |
422 break; | |
423 case Bytecodes::_dup_x2: | |
424 a = pop(); | |
425 b = pop(); | |
426 c = pop(); | |
427 push(a); | |
428 push(c); | |
429 push(b); | |
430 push(a); | |
431 break; | |
432 case Bytecodes::_dup2: | |
433 a = pop(); | |
434 b = pop(); | |
435 push(b); | |
436 push(a); | |
437 push(b); | |
438 push(a); | |
439 break; | |
440 case Bytecodes::_dup2_x1: | |
441 a = pop(); | |
442 b = pop(); | |
443 c = pop(); | |
444 push(b); | |
445 push(a); | |
446 push(c); | |
447 push(b); | |
448 push(a); | |
449 break; | |
450 case Bytecodes::_dup2_x2: | |
451 a = pop(); | |
452 b = pop(); | |
453 c = pop(); | |
454 d = pop(); | |
455 push(b); | |
456 push(a); | |
457 push(d); | |
458 push(c); | |
459 push(b); | |
460 push(a); | |
461 break; | |
462 | |
463 case Bytecodes::_getfield: | |
464 if (!do_getfield()) | |
465 return false; | |
466 break; | |
467 case Bytecodes::_getstatic: | |
468 if (!do_getstatic()) | |
469 return false; | |
470 break; | |
471 case Bytecodes::_putfield: | |
472 if (!do_putfield()) | |
473 return false; | |
474 break; | |
475 | |
476 case Bytecodes::_iadd: | |
477 case Bytecodes::_isub: | |
478 case Bytecodes::_imul: | |
479 case Bytecodes::_iand: | |
480 case Bytecodes::_ixor: | |
481 case Bytecodes::_ishl: | |
482 case Bytecodes::_ishr: | |
483 case Bytecodes::_iushr: | |
484 pop(); | |
485 pop(); | |
486 push(false); | |
487 break; | |
488 case Bytecodes::_ior: | |
489 a = pop(); | |
490 b = pop(); | |
491 push(a && b); | |
492 break; | |
493 case Bytecodes::_idiv: | |
494 case Bytecodes::_irem: | |
495 if (!pop()) | |
496 return false; | |
497 pop(); | |
498 push(false); | |
499 break; | |
500 case Bytecodes::_ineg: | |
501 break; | |
502 | |
503 case Bytecodes::_ladd: | |
504 case Bytecodes::_lsub: | |
505 case Bytecodes::_lmul: | |
506 case Bytecodes::_land: | |
507 case Bytecodes::_lxor: | |
508 pop(); | |
509 pop(); | |
510 pop(); | |
511 pop(); | |
512 push(false); | |
513 push(false); | |
514 break; | |
515 case Bytecodes::_lor: | |
516 a = pop(); | |
517 b = pop(); | |
518 push(a && b); | |
519 break; | |
520 case Bytecodes::_ldiv: | |
521 case Bytecodes::_lrem: | |
522 pop(); | |
523 if (!pop()) | |
524 return false; | |
525 pop(); | |
526 pop(); | |
527 push(false); | |
528 push(false); | |
529 break; | |
530 case Bytecodes::_lneg: | |
531 break; | |
532 case Bytecodes::_lshl: | |
533 case Bytecodes::_lshr: | |
534 case Bytecodes::_lushr: | |
535 pop(); | |
536 pop(); | |
537 pop(); | |
538 push(false); | |
539 push(false); | |
540 break; | |
541 | |
542 case Bytecodes::_fadd: | |
543 case Bytecodes::_fsub: | |
544 case Bytecodes::_fmul: | |
545 case Bytecodes::_fdiv: | |
546 case Bytecodes::_frem: | |
547 pop(); | |
548 pop(); | |
549 push(false); | |
550 break; | |
551 case Bytecodes::_fneg: | |
552 break; | |
553 | |
554 case Bytecodes::_dadd: | |
555 case Bytecodes::_dsub: | |
556 case Bytecodes::_dmul: | |
557 case Bytecodes::_ddiv: | |
558 case Bytecodes::_drem: | |
559 pop(); | |
560 pop(); | |
561 pop(); | |
562 pop(); | |
563 push(false); | |
564 push(false); | |
565 break; | |
566 case Bytecodes::_dneg: | |
567 break; | |
568 | |
569 case Bytecodes::_iinc: | |
570 set_local(iter()->get_index(), false); | |
571 break; | |
572 | |
573 case Bytecodes::_lcmp: | |
574 pop(); | |
575 pop(); | |
576 pop(); | |
577 pop(); | |
578 push(false); | |
579 break; | |
580 | |
581 case Bytecodes::_fcmpl: | |
582 case Bytecodes::_fcmpg: | |
583 pop(); | |
584 pop(); | |
585 push(false); | |
586 break; | |
587 | |
588 case Bytecodes::_dcmpl: | |
589 case Bytecodes::_dcmpg: | |
590 pop(); | |
591 pop(); | |
592 pop(); | |
593 pop(); | |
594 push(false); | |
595 break; | |
596 | |
597 case Bytecodes::_i2l: | |
598 push(false); | |
599 break; | |
600 case Bytecodes::_i2f: | |
601 pop(); | |
602 push(false); | |
603 break; | |
604 case Bytecodes::_i2d: | |
605 pop(); | |
606 push(false); | |
607 push(false); | |
608 break; | |
609 | |
610 case Bytecodes::_l2i: | |
611 case Bytecodes::_l2f: | |
612 pop(); | |
613 pop(); | |
614 push(false); | |
615 break; | |
616 case Bytecodes::_l2d: | |
617 pop(); | |
618 pop(); | |
619 push(false); | |
620 push(false); | |
621 break; | |
622 | |
623 case Bytecodes::_f2i: | |
624 pop(); | |
625 push(false); | |
626 break; | |
627 case Bytecodes::_f2l: | |
628 case Bytecodes::_f2d: | |
629 pop(); | |
630 push(false); | |
631 push(false); | |
632 break; | |
633 | |
634 case Bytecodes::_d2i: | |
635 case Bytecodes::_d2f: | |
636 pop(); | |
637 pop(); | |
638 push(false); | |
639 break; | |
640 case Bytecodes::_d2l: | |
641 pop(); | |
642 pop(); | |
643 push(false); | |
644 push(false); | |
645 break; | |
646 | |
647 case Bytecodes::_i2b: | |
648 case Bytecodes::_i2c: | |
649 case Bytecodes::_i2s: | |
650 pop(); | |
651 push(false); | |
652 break; | |
653 | |
654 case Bytecodes::_return: | |
655 case Bytecodes::_ireturn: | |
656 case Bytecodes::_lreturn: | |
657 case Bytecodes::_freturn: | |
658 case Bytecodes::_dreturn: | |
659 case Bytecodes::_areturn: | |
660 break; | |
661 | |
662 default: | |
663 return false; | |
664 } | |
665 } | |
666 | |
667 return true; | |
668 } | |
669 | |
670 void SharkInlinerHelper::initialize_for_check() { | |
671 _locals = NEW_RESOURCE_ARRAY(bool, max_locals()); | |
672 _stack = NEW_RESOURCE_ARRAY(bool, max_stack()); | |
673 | |
674 memset(_locals, 0, max_locals() * sizeof(bool)); | |
675 for (int i = 0; i < target()->arg_size(); i++) { | |
676 SharkValue *arg = entry_state()->stack(target()->arg_size() - 1 - i); | |
677 if (arg && arg->zero_checked()) | |
678 set_local(i, true); | |
679 } | |
680 | |
681 _sp = _stack; | |
682 } | |
683 | |
684 bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) { | |
685 assert(is_get || is_field, "can't inline putstatic"); | |
686 | |
687 // If the holder isn't linked then there isn't a lot we can do | |
688 if (!target()->holder()->is_linked()) | |
689 return false; | |
690 | |
691 // Get the field | |
692 bool will_link; | |
693 ciField *field = iter()->get_field(will_link); | |
694 if (!will_link) | |
695 return false; | |
696 | |
697 // If the field is mismatched then an exception needs throwing | |
698 if (is_field == field->is_static()) | |
699 return false; | |
700 | |
701 // Pop the value off the stack if necessary | |
702 if (!is_get) { | |
703 pop(); | |
704 if (field->type()->is_two_word()) | |
705 pop(); | |
706 } | |
707 | |
708 // Pop and null-check the receiver if necessary | |
709 if (is_field) { | |
710 if (!pop()) | |
711 return false; | |
712 } | |
713 | |
714 // Push the result if necessary | |
715 if (is_get) { | |
716 bool result_pushed = false; | |
717 if (field->is_constant()) { | |
718 SharkConstant *sc = SharkConstant::for_field(iter()); | |
719 if (sc->is_loaded()) { | |
720 push(sc->is_nonzero()); | |
721 result_pushed = true; | |
722 } | |
723 } | |
724 | |
725 if (!result_pushed) | |
726 push(false); | |
727 | |
728 if (field->type()->is_two_word()) | |
729 push(false); | |
730 } | |
731 | |
732 return true; | |
733 } | |
734 | |
735 bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state) { | |
736 if (SharkIntrinsics::is_intrinsic(target)) { | |
737 SharkIntrinsics::inline_intrinsic(target, state); | |
738 return true; | |
739 } | |
740 | |
741 if (may_be_inlinable(target)) { | |
742 SharkInlinerHelper inliner(target, state); | |
743 if (inliner.is_inlinable()) { | |
744 inliner.do_inline(); | |
745 return true; | |
746 } | |
747 } | |
748 return false; | |
749 } |