forked from openjdk/jdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse1.cpp
2385 lines (2091 loc) · 89.5 KB
/
parse1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/resourceArea.hpp"
#include "oops/method.hpp"
#include "opto/addnode.hpp"
#include "opto/c2compiler.hpp"
#include "opto/castnode.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/locknode.hpp"
#include "opto/memnode.hpp"
#include "opto/opaquenode.hpp"
#include "opto/parse.hpp"
#include "opto/rootnode.hpp"
#include "opto/runtime.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/safepointMechanism.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/copy.hpp"
// Static array so we can figure out which bytecodes stop us from compiling
// the most. Some of the non-static variables are needed in bytecodeInfo.cpp
// and eventually should be encapsulated in a proper class (gri 8/18/98).
#ifndef PRODUCT
int nodes_created = 0;
int methods_parsed = 0;
int methods_seen = 0;
int blocks_parsed = 0;
int blocks_seen = 0;
int explicit_null_checks_inserted = 0;
int explicit_null_checks_elided = 0;
int all_null_checks_found = 0;
int implicit_null_checks = 0;
bool Parse::BytecodeParseHistogram::_initialized = false;
uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes];
//------------------------------print_statistics-------------------------------
void Parse::print_statistics() {
tty->print_cr("--- Compiler Statistics ---");
tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed);
tty->print(" Nodes created: %d", nodes_created);
tty->cr();
if (methods_seen != methods_parsed) {
tty->print_cr("Reasons for parse failures (NOT cumulative):");
}
tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen);
if (explicit_null_checks_inserted) {
tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,",
explicit_null_checks_inserted, explicit_null_checks_elided,
(100*explicit_null_checks_elided)/explicit_null_checks_inserted,
all_null_checks_found);
}
if (all_null_checks_found) {
tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks,
(100*implicit_null_checks)/all_null_checks_found);
}
if (SharedRuntime::_implicit_null_throws) {
tty->print_cr("%d implicit null exceptions at runtime",
SharedRuntime::_implicit_null_throws);
}
if (PrintParseStatistics && BytecodeParseHistogram::initialized()) {
BytecodeParseHistogram::print();
}
}
#endif
//------------------------------ON STACK REPLACEMENT---------------------------
// Construct a node which can be used to get incoming state for
// on stack replacement.
Node *Parse::fetch_interpreter_state(int index,
BasicType bt,
Node *local_addrs,
Node *local_addrs_base) {
Node *mem = memory(Compile::AliasIdxRaw);
Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
Node *ctl = control();
// Very similar to LoadNode::make, except we handle un-aligned longs and
// doubles on Sparc. Intel can handle them just fine directly.
Node *l = NULL;
switch (bt) { // Signature is flattened
case T_INT: l = new LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT, MemNode::unordered); break;
case T_FLOAT: l = new LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT, MemNode::unordered); break;
case T_ADDRESS: l = new LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered); break;
case T_OBJECT: l = new LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM, MemNode::unordered); break;
case T_LONG:
case T_DOUBLE: {
// Since arguments are in reverse order, the argument address 'adr'
// refers to the back half of the long/double. Recompute adr.
adr = basic_plus_adr(local_addrs_base, local_addrs, -(index+1)*wordSize);
if (Matcher::misaligned_doubles_ok) {
l = (bt == T_DOUBLE)
? (Node*)new LoadDNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::DOUBLE, MemNode::unordered)
: (Node*)new LoadLNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeLong::LONG, MemNode::unordered);
} else {
l = (bt == T_DOUBLE)
? (Node*)new LoadD_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered)
: (Node*)new LoadL_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered);
}
break;
}
default: ShouldNotReachHere();
}
return _gvn.transform(l);
}
// Helper routine to prevent the interpreter from handing
// unexpected typestate to an OSR method.
// The Node l is a value newly dug out of the interpreter frame.
// The type is the type predicted by ciTypeFlow. Note that it is
// not a general type, but can only come from Type::get_typeflow_type.
// The safepoint is a map which will feed an uncommon trap.
Node* Parse::check_interpreter_type(Node* l, const Type* type,
SafePointNode* &bad_type_exit) {
const TypeOopPtr* tp = type->isa_oopptr();
// TypeFlow may assert null-ness if a type appears unloaded.
if (type == TypePtr::NULL_PTR ||
(tp != NULL && !tp->klass()->is_loaded())) {
// Value must be null, not a real oop.
Node* chk = _gvn.transform( new CmpPNode(l, null()) );
Node* tst = _gvn.transform( new BoolNode(chk, BoolTest::eq) );
IfNode* iff = create_and_map_if(control(), tst, PROB_MAX, COUNT_UNKNOWN);
set_control(_gvn.transform( new IfTrueNode(iff) ));
Node* bad_type = _gvn.transform( new IfFalseNode(iff) );
bad_type_exit->control()->add_req(bad_type);
l = null();
}
// Typeflow can also cut off paths from the CFG, based on
// types which appear unloaded, or call sites which appear unlinked.
// When paths are cut off, values at later merge points can rise
// toward more specific classes. Make sure these specific classes
// are still in effect.
if (tp != NULL && tp->klass() != C->env()->Object_klass()) {
// TypeFlow asserted a specific object type. Value must have that type.
Node* bad_type_ctrl = NULL;
l = gen_checkcast(l, makecon(TypeKlassPtr::make(tp->klass())), &bad_type_ctrl);
bad_type_exit->control()->add_req(bad_type_ctrl);
}
BasicType bt_l = _gvn.type(l)->basic_type();
BasicType bt_t = type->basic_type();
assert(_gvn.type(l)->higher_equal(type), "must constrain OSR typestate");
return l;
}
// Helper routine which sets up elements of the initial parser map when
// performing a parse for on stack replacement. Add values into map.
// The only parameter contains the address of a interpreter arguments.
void Parse::load_interpreter_state(Node* osr_buf) {
int index;
int max_locals = jvms()->loc_size();
int max_stack = jvms()->stk_size();
// Mismatch between method and jvms can occur since map briefly held
// an OSR entry state (which takes up one RawPtr word).
assert(max_locals == method()->max_locals(), "sanity");
assert(max_stack >= method()->max_stack(), "sanity");
assert((int)jvms()->endoff() == TypeFunc::Parms + max_locals + max_stack, "sanity");
assert((int)jvms()->endoff() == (int)map()->req(), "sanity");
// Find the start block.
Block* osr_block = start_block();
assert(osr_block->start() == osr_bci(), "sanity");
// Set initial BCI.
set_parse_bci(osr_block->start());
// Set initial stack depth.
set_sp(osr_block->start_sp());
// Check bailouts. We currently do not perform on stack replacement
// of loops in catch blocks or loops which branch with a non-empty stack.
if (sp() != 0) {
C->record_method_not_compilable("OSR starts with non-empty stack");
return;
}
// Do not OSR inside finally clauses:
if (osr_block->has_trap_at(osr_block->start())) {
C->record_method_not_compilable("OSR starts with an immediate trap");
return;
}
// Commute monitors from interpreter frame to compiler frame.
assert(jvms()->monitor_depth() == 0, "should be no active locks at beginning of osr");
int mcnt = osr_block->flow()->monitor_count();
Node *monitors_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals+mcnt*2-1)*wordSize);
for (index = 0; index < mcnt; index++) {
// Make a BoxLockNode for the monitor.
Node *box = _gvn.transform(new BoxLockNode(next_monitor()));
// Displaced headers and locked objects are interleaved in the
// temp OSR buffer. We only copy the locked objects out here.
// Fetch the locked object from the OSR temp buffer and copy to our fastlock node.
Node *lock_object = fetch_interpreter_state(index*2, T_OBJECT, monitors_addr, osr_buf);
// Try and copy the displaced header to the BoxNode
Node *displaced_hdr = fetch_interpreter_state((index*2) + 1, T_ADDRESS, monitors_addr, osr_buf);
store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered);
// Build a bogus FastLockNode (no code will be generated) and push the
// monitor into our debug info.
const FastLockNode *flock = _gvn.transform(new FastLockNode( 0, lock_object, box ))->as_FastLock();
map()->push_monitor(flock);
// If the lock is our method synchronization lock, tuck it away in
// _sync_lock for return and rethrow exit paths.
if (index == 0 && method()->is_synchronized()) {
_synch_lock = flock;
}
}
// Use the raw liveness computation to make sure that unexpected
// values don't propagate into the OSR frame.
MethodLivenessResult live_locals = method()->liveness_at_bci(osr_bci());
if (!live_locals.is_valid()) {
// Degenerate or breakpointed method.
C->record_method_not_compilable("OSR in empty or breakpointed method");
return;
}
// Extract the needed locals from the interpreter frame.
Node *locals_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals-1)*wordSize);
// find all the locals that the interpreter thinks contain live oops
const ResourceBitMap live_oops = method()->live_local_oops_at_bci(osr_bci());
for (index = 0; index < max_locals; index++) {
if (!live_locals.at(index)) {
continue;
}
const Type *type = osr_block->local_type_at(index);
if (type->isa_oopptr() != NULL) {
// 6403625: Verify that the interpreter oopMap thinks that the oop is live
// else we might load a stale oop if the MethodLiveness disagrees with the
// result of the interpreter. If the interpreter says it is dead we agree
// by making the value go to top.
//
if (!live_oops.at(index)) {
if (C->log() != NULL) {
C->log()->elem("OSR_mismatch local_index='%d'",index);
}
set_local(index, null());
// and ignore it for the loads
continue;
}
}
// Filter out TOP, HALF, and BOTTOM. (Cf. ensure_phi.)
if (type == Type::TOP || type == Type::HALF) {
continue;
}
// If the type falls to bottom, then this must be a local that
// is mixing ints and oops or some such. Forcing it to top
// makes it go dead.
if (type == Type::BOTTOM) {
continue;
}
// Construct code to access the appropriate local.
BasicType bt = type->basic_type();
if (type == TypePtr::NULL_PTR) {
// Ptr types are mixed together with T_ADDRESS but NULL is
// really for T_OBJECT types so correct it.
bt = T_OBJECT;
}
Node *value = fetch_interpreter_state(index, bt, locals_addr, osr_buf);
set_local(index, value);
}
// Extract the needed stack entries from the interpreter frame.
for (index = 0; index < sp(); index++) {
const Type *type = osr_block->stack_type_at(index);
if (type != Type::TOP) {
// Currently the compiler bails out when attempting to on stack replace
// at a bci with a non-empty stack. We should not reach here.
ShouldNotReachHere();
}
}
// End the OSR migration
make_runtime_call(RC_LEAF, OptoRuntime::osr_end_Type(),
CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end),
"OSR_migration_end", TypeRawPtr::BOTTOM,
osr_buf);
// Now that the interpreter state is loaded, make sure it will match
// at execution time what the compiler is expecting now:
SafePointNode* bad_type_exit = clone_map();
bad_type_exit->set_control(new RegionNode(1));
assert(osr_block->flow()->jsrs()->size() == 0, "should be no jsrs live at osr point");
for (index = 0; index < max_locals; index++) {
if (stopped()) break;
Node* l = local(index);
if (l->is_top()) continue; // nothing here
const Type *type = osr_block->local_type_at(index);
if (type->isa_oopptr() != NULL) {
if (!live_oops.at(index)) {
// skip type check for dead oops
continue;
}
}
if (osr_block->flow()->local_type_at(index)->is_return_address()) {
// In our current system it's illegal for jsr addresses to be
// live into an OSR entry point because the compiler performs
// inlining of jsrs. ciTypeFlow has a bailout that detect this
// case and aborts the compile if addresses are live into an OSR
// entry point. Because of that we can assume that any address
// locals at the OSR entry point are dead. Method liveness
// isn't precise enought to figure out that they are dead in all
// cases so simply skip checking address locals all
// together. Any type check is guaranteed to fail since the
// interpreter type is the result of a load which might have any
// value and the expected type is a constant.
continue;
}
set_local(index, check_interpreter_type(l, type, bad_type_exit));
}
for (index = 0; index < sp(); index++) {
if (stopped()) break;
Node* l = stack(index);
if (l->is_top()) continue; // nothing here
const Type *type = osr_block->stack_type_at(index);
set_stack(index, check_interpreter_type(l, type, bad_type_exit));
}
if (bad_type_exit->control()->req() > 1) {
// Build an uncommon trap here, if any inputs can be unexpected.
bad_type_exit->set_control(_gvn.transform( bad_type_exit->control() ));
record_for_igvn(bad_type_exit->control());
SafePointNode* types_are_good = map();
set_map(bad_type_exit);
// The unexpected type happens because a new edge is active
// in the CFG, which typeflow had previously ignored.
// E.g., Object x = coldAtFirst() && notReached()? "str": new Integer(123).
// This x will be typed as Integer if notReached is not yet linked.
// It could also happen due to a problem in ciTypeFlow analysis.
uncommon_trap(Deoptimization::Reason_constraint,
Deoptimization::Action_reinterpret);
set_map(types_are_good);
}
}
//------------------------------Parse------------------------------------------
// Main parser constructor.
Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
: _exits(caller)
{
// Init some variables
_caller = caller;
_method = parse_method;
_expected_uses = expected_uses;
_depth = 1 + (caller->has_method() ? caller->depth() : 0);
_wrote_final = false;
_wrote_volatile = false;
_wrote_stable = false;
_wrote_fields = false;
_alloc_with_final = NULL;
_entry_bci = InvocationEntryBci;
_tf = NULL;
_block = NULL;
_first_return = true;
_replaced_nodes_for_exceptions = false;
_new_idx = C->unique();
debug_only(_block_count = -1);
debug_only(_blocks = (Block*)-1);
#ifndef PRODUCT
if (PrintCompilation || PrintOpto) {
// Make sure I have an inline tree, so I can print messages about it.
JVMState* ilt_caller = is_osr_parse() ? caller->caller() : caller;
InlineTree::find_subtree_from_root(C->ilt(), ilt_caller, parse_method);
}
_max_switch_depth = 0;
_est_switch_depth = 0;
#endif
if (parse_method->has_reserved_stack_access()) {
C->set_has_reserved_stack_access(true);
}
_tf = TypeFunc::make(method());
_iter.reset_to_method(method());
_flow = method()->get_flow_analysis();
if (_flow->failing()) {
C->record_method_not_compilable(_flow->failure_reason());
}
#ifndef PRODUCT
if (_flow->has_irreducible_entry()) {
C->set_parsed_irreducible_loop(true);
}
#endif
C->set_has_loops(C->has_loops() || method()->has_loops());
if (_expected_uses <= 0) {
_prof_factor = 1;
} else {
float prof_total = parse_method->interpreter_invocation_count();
if (prof_total <= _expected_uses) {
_prof_factor = 1;
} else {
_prof_factor = _expected_uses / prof_total;
}
}
CompileLog* log = C->log();
if (log != NULL) {
log->begin_head("parse method='%d' uses='%f'",
log->identify(parse_method), expected_uses);
if (depth() == 1 && C->is_osr_compilation()) {
log->print(" osr_bci='%d'", C->entry_bci());
}
log->stamp();
log->end_head();
}
// Accumulate deoptimization counts.
// (The range_check and store_check counts are checked elsewhere.)
ciMethodData* md = method()->method_data();
for (uint reason = 0; reason < md->trap_reason_limit(); reason++) {
uint md_count = md->trap_count(reason);
if (md_count != 0) {
if (md_count == md->trap_count_limit())
md_count += md->overflow_trap_count();
uint total_count = C->trap_count(reason);
uint old_count = total_count;
total_count += md_count;
// Saturate the add if it overflows.
if (total_count < old_count || total_count < md_count)
total_count = (uint)-1;
C->set_trap_count(reason, total_count);
if (log != NULL)
log->elem("observe trap='%s' count='%d' total='%d'",
Deoptimization::trap_reason_name(reason),
md_count, total_count);
}
}
// Accumulate total sum of decompilations, also.
C->set_decompile_count(C->decompile_count() + md->decompile_count());
if (log != NULL && method()->has_exception_handlers()) {
log->elem("observe that='has_exception_handlers'");
}
assert(InlineTree::check_can_parse(method()) == NULL, "Can not parse this method, cutout earlier");
assert(method()->has_balanced_monitors(), "Can not parse unbalanced monitors, cutout earlier");
// Always register dependence if JVMTI is enabled, because
// either breakpoint setting or hotswapping of methods may
// cause deoptimization.
if (C->env()->jvmti_can_hotswap_or_post_breakpoint()) {
C->dependencies()->assert_evol_method(method());
}
NOT_PRODUCT(methods_seen++);
// Do some special top-level things.
if (depth() == 1 && C->is_osr_compilation()) {
_entry_bci = C->entry_bci();
_flow = method()->get_osr_flow_analysis(osr_bci());
if (_flow->failing()) {
C->record_method_not_compilable(_flow->failure_reason());
#ifndef PRODUCT
if (PrintOpto && (Verbose || WizardMode)) {
tty->print_cr("OSR @%d type flow bailout: %s", _entry_bci, _flow->failure_reason());
if (Verbose) {
method()->print();
method()->print_codes();
_flow->print();
}
}
#endif
}
_tf = C->tf(); // the OSR entry type is different
}
#ifdef ASSERT
if (depth() == 1) {
assert(C->is_osr_compilation() == this->is_osr_parse(), "OSR in sync");
} else {
assert(!this->is_osr_parse(), "no recursive OSR");
}
#endif
#ifndef PRODUCT
methods_parsed++;
// add method size here to guarantee that inlined methods are added too
if (CITime)
_total_bytes_compiled += method()->code_size();
show_parse_info();
#endif
if (failing()) {
if (log) log->done("parse");
return;
}
gvn().set_type(root(), root()->bottom_type());
gvn().transform(top());
// Import the results of the ciTypeFlow.
init_blocks();
// Merge point for all normal exits
build_exits();
// Setup the initial JVM state map.
SafePointNode* entry_map = create_entry_map();
// Check for bailouts during map initialization
if (failing() || entry_map == NULL) {
if (log) log->done("parse");
return;
}
Node_Notes* caller_nn = C->default_node_notes();
// Collect debug info for inlined calls unless -XX:-DebugInlinedCalls.
if (DebugInlinedCalls || depth() == 1) {
C->set_default_node_notes(make_node_notes(caller_nn));
}
if (is_osr_parse()) {
Node* osr_buf = entry_map->in(TypeFunc::Parms+0);
entry_map->set_req(TypeFunc::Parms+0, top());
set_map(entry_map);
load_interpreter_state(osr_buf);
} else {
set_map(entry_map);
do_method_entry();
if (depth() == 1 && C->age_code()) {
decrement_age();
}
}
if (depth() == 1 && !failing()) {
if (C->clinit_barrier_on_entry()) {
// Add check to deoptimize the nmethod once the holder class is fully initialized
clinit_deopt();
}
// Add check to deoptimize the nmethod if RTM state was changed
rtm_deopt();
}
// Check for bailouts during method entry or RTM state check setup.
if (failing()) {
if (log) log->done("parse");
C->set_default_node_notes(caller_nn);
return;
}
entry_map = map(); // capture any changes performed by method setup code
assert(jvms()->endoff() == map()->req(), "map matches JVMS layout");
// We begin parsing as if we have just encountered a jump to the
// method entry.
Block* entry_block = start_block();
assert(entry_block->start() == (is_osr_parse() ? osr_bci() : 0), "");
set_map_clone(entry_map);
merge_common(entry_block, entry_block->next_path_num());
#ifndef PRODUCT
BytecodeParseHistogram *parse_histogram_obj = new (C->env()->arena()) BytecodeParseHistogram(this, C);
set_parse_histogram( parse_histogram_obj );
#endif
// Parse all the basic blocks.
do_all_blocks();
C->set_default_node_notes(caller_nn);
// Check for bailouts during conversion to graph
if (failing()) {
if (log) log->done("parse");
return;
}
// Fix up all exiting control flow.
set_map(entry_map);
do_exits();
if (log) log->done("parse nodes='%d' live='%d' memory='" SIZE_FORMAT "'",
C->unique(), C->live_nodes(), C->node_arena()->used());
}
//---------------------------do_all_blocks-------------------------------------
void Parse::do_all_blocks() {
bool has_irreducible = flow()->has_irreducible_entry();
// Walk over all blocks in Reverse Post-Order.
while (true) {
bool progress = false;
for (int rpo = 0; rpo < block_count(); rpo++) {
Block* block = rpo_at(rpo);
if (block->is_parsed()) continue;
if (!block->is_merged()) {
// Dead block, no state reaches this block
continue;
}
// Prepare to parse this block.
load_state_from(block);
if (stopped()) {
// Block is dead.
continue;
}
NOT_PRODUCT(blocks_parsed++);
progress = true;
if (block->is_loop_head() || block->is_handler() || (has_irreducible && !block->is_ready())) {
// Not all preds have been parsed. We must build phis everywhere.
// (Note that dead locals do not get phis built, ever.)
ensure_phis_everywhere();
if (block->is_SEL_head()) {
// Add predicate to single entry (not irreducible) loop head.
assert(!block->has_merged_backedge(), "only entry paths should be merged for now");
// Predicates may have been added after a dominating if
if (!block->has_predicates()) {
// Need correct bci for predicate.
// It is fine to set it here since do_one_block() will set it anyway.
set_parse_bci(block->start());
add_empty_predicates();
}
// Add new region for back branches.
int edges = block->pred_count() - block->preds_parsed() + 1; // +1 for original region
RegionNode *r = new RegionNode(edges+1);
_gvn.set_type(r, Type::CONTROL);
record_for_igvn(r);
r->init_req(edges, control());
set_control(r);
// Add new phis.
ensure_phis_everywhere();
}
// Leave behind an undisturbed copy of the map, for future merges.
set_map(clone_map());
}
if (control()->is_Region() && !block->is_loop_head() && !has_irreducible && !block->is_handler()) {
// In the absence of irreducible loops, the Region and Phis
// associated with a merge that doesn't involve a backedge can
// be simplified now since the RPO parsing order guarantees
// that any path which was supposed to reach here has already
// been parsed or must be dead.
Node* c = control();
Node* result = _gvn.transform_no_reclaim(control());
if (c != result && TraceOptoParse) {
tty->print_cr("Block #%d replace %d with %d", block->rpo(), c->_idx, result->_idx);
}
if (result != top()) {
record_for_igvn(result);
}
}
// Parse the block.
do_one_block();
// Check for bailouts.
if (failing()) return;
}
// with irreducible loops multiple passes might be necessary to parse everything
if (!has_irreducible || !progress) {
break;
}
}
#ifndef PRODUCT
blocks_seen += block_count();
// Make sure there are no half-processed blocks remaining.
// Every remaining unprocessed block is dead and may be ignored now.
for (int rpo = 0; rpo < block_count(); rpo++) {
Block* block = rpo_at(rpo);
if (!block->is_parsed()) {
if (TraceOptoParse) {
tty->print_cr("Skipped dead block %d at bci:%d", rpo, block->start());
}
assert(!block->is_merged(), "no half-processed blocks");
}
}
#endif
}
static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) {
switch (bt) {
case T_BYTE:
v = gvn->transform(new LShiftINode(v, gvn->intcon(24)));
v = gvn->transform(new RShiftINode(v, gvn->intcon(24)));
break;
case T_SHORT:
v = gvn->transform(new LShiftINode(v, gvn->intcon(16)));
v = gvn->transform(new RShiftINode(v, gvn->intcon(16)));
break;
case T_CHAR:
v = gvn->transform(new AndINode(v, gvn->intcon(0xFFFF)));
break;
case T_BOOLEAN:
v = gvn->transform(new AndINode(v, gvn->intcon(0x1)));
break;
default:
break;
}
return v;
}
//-------------------------------build_exits----------------------------------
// Build normal and exceptional exit merge points.
void Parse::build_exits() {
// make a clone of caller to prevent sharing of side-effects
_exits.set_map(_exits.clone_map());
_exits.clean_stack(_exits.sp());
_exits.sync_jvms();
RegionNode* region = new RegionNode(1);
record_for_igvn(region);
gvn().set_type_bottom(region);
_exits.set_control(region);
// Note: iophi and memphi are not transformed until do_exits.
Node* iophi = new PhiNode(region, Type::ABIO);
Node* memphi = new PhiNode(region, Type::MEMORY, TypePtr::BOTTOM);
gvn().set_type_bottom(iophi);
gvn().set_type_bottom(memphi);
_exits.set_i_o(iophi);
_exits.set_all_memory(memphi);
// Add a return value to the exit state. (Do not push it yet.)
if (tf()->range()->cnt() > TypeFunc::Parms) {
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
if (ret_type->isa_int()) {
BasicType ret_bt = method()->return_type()->basic_type();
if (ret_bt == T_BOOLEAN ||
ret_bt == T_CHAR ||
ret_bt == T_BYTE ||
ret_bt == T_SHORT) {
ret_type = TypeInt::INT;
}
}
// Don't "bind" an unloaded return klass to the ret_phi. If the klass
// becomes loaded during the subsequent parsing, the loaded and unloaded
// types will not join when we transform and push in do_exits().
const TypeOopPtr* ret_oop_type = ret_type->isa_oopptr();
if (ret_oop_type && !ret_oop_type->klass()->is_loaded()) {
ret_type = TypeOopPtr::BOTTOM;
}
int ret_size = type2size[ret_type->basic_type()];
Node* ret_phi = new PhiNode(region, ret_type);
gvn().set_type_bottom(ret_phi);
_exits.ensure_stack(ret_size);
assert((int)(tf()->range()->cnt() - TypeFunc::Parms) == ret_size, "good tf range");
assert(method()->return_type()->size() == ret_size, "tf agrees w/ method");
_exits.set_argument(0, ret_phi); // here is where the parser finds it
// Note: ret_phi is not yet pushed, until do_exits.
}
}
//----------------------------build_start_state-------------------------------
// Construct a state which contains only the incoming arguments from an
// unknown caller. The method & bci will be NULL & InvocationEntryBci.
JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
int arg_size = tf->domain()->cnt();
int max_size = MAX2(arg_size, (int)tf->range()->cnt());
JVMState* jvms = new (this) JVMState(max_size - TypeFunc::Parms);
SafePointNode* map = new SafePointNode(max_size, jvms);
record_for_igvn(map);
assert(arg_size == TypeFunc::Parms + (is_osr_compilation() ? 1 : method()->arg_size()), "correct arg_size");
Node_Notes* old_nn = default_node_notes();
if (old_nn != NULL && has_method()) {
Node_Notes* entry_nn = old_nn->clone(this);
JVMState* entry_jvms = new(this) JVMState(method(), old_nn->jvms());
entry_jvms->set_offsets(0);
entry_jvms->set_bci(entry_bci());
entry_nn->set_jvms(entry_jvms);
set_default_node_notes(entry_nn);
}
uint i;
for (i = 0; i < (uint)arg_size; i++) {
Node* parm = initial_gvn()->transform(new ParmNode(start, i));
map->init_req(i, parm);
// Record all these guys for later GVN.
record_for_igvn(parm);
}
for (; i < map->req(); i++) {
map->init_req(i, top());
}
assert(jvms->argoff() == TypeFunc::Parms, "parser gets arguments here");
set_default_node_notes(old_nn);
jvms->set_map(map);
return jvms;
}
//-----------------------------make_node_notes---------------------------------
Node_Notes* Parse::make_node_notes(Node_Notes* caller_nn) {
if (caller_nn == NULL) return NULL;
Node_Notes* nn = caller_nn->clone(C);
JVMState* caller_jvms = nn->jvms();
JVMState* jvms = new (C) JVMState(method(), caller_jvms);
jvms->set_offsets(0);
jvms->set_bci(_entry_bci);
nn->set_jvms(jvms);
return nn;
}
//--------------------------return_values--------------------------------------
void Compile::return_values(JVMState* jvms) {
GraphKit kit(jvms);
Node* ret = new ReturnNode(TypeFunc::Parms,
kit.control(),
kit.i_o(),
kit.reset_memory(),
kit.frameptr(),
kit.returnadr());
// Add zero or 1 return values
int ret_size = tf()->range()->cnt() - TypeFunc::Parms;
if (ret_size > 0) {
kit.inc_sp(-ret_size); // pop the return value(s)
kit.sync_jvms();
ret->add_req(kit.argument(0));
// Note: The second dummy edge is not needed by a ReturnNode.
}
// bind it to root
root()->add_req(ret);
record_for_igvn(ret);
initial_gvn()->transform_no_reclaim(ret);
}
//------------------------rethrow_exceptions-----------------------------------
// Bind all exception states in the list into a single RethrowNode.
void Compile::rethrow_exceptions(JVMState* jvms) {
GraphKit kit(jvms);
if (!kit.has_exceptions()) return; // nothing to generate
// Load my combined exception state into the kit, with all phis transformed:
SafePointNode* ex_map = kit.combine_and_pop_all_exception_states();
Node* ex_oop = kit.use_exception_state(ex_map);
RethrowNode* exit = new RethrowNode(kit.control(),
kit.i_o(), kit.reset_memory(),
kit.frameptr(), kit.returnadr(),
// like a return but with exception input
ex_oop);
// bind to root
root()->add_req(exit);
record_for_igvn(exit);
initial_gvn()->transform_no_reclaim(exit);
}
//---------------------------do_exceptions-------------------------------------
// Process exceptions arising from the current bytecode.
// Send caught exceptions to the proper handler within this method.
// Unhandled exceptions feed into _exit.
void Parse::do_exceptions() {
if (!has_exceptions()) return;
if (failing()) {
// Pop them all off and throw them away.
while (pop_exception_state() != NULL) ;
return;
}
PreserveJVMState pjvms(this, false);
SafePointNode* ex_map;
while ((ex_map = pop_exception_state()) != NULL) {
if (!method()->has_exception_handlers()) {
// Common case: Transfer control outward.
// Doing it this early allows the exceptions to common up
// even between adjacent method calls.
throw_to_exit(ex_map);
} else {
// Have to look at the exception first.
assert(stopped(), "catch_inline_exceptions trashes the map");
catch_inline_exceptions(ex_map);
stop_and_kill_map(); // we used up this exception state; kill it
}
}
// We now return to our regularly scheduled program:
}
//---------------------------throw_to_exit-------------------------------------
// Merge the given map into an exception exit from this method.
// The exception exit will handle any unlocking of receiver.
// The ex_oop must be saved within the ex_map, unlike merge_exception.
void Parse::throw_to_exit(SafePointNode* ex_map) {
// Pop the JVMS to (a copy of) the caller.
GraphKit caller;
caller.set_map_clone(_caller->map());
caller.set_bci(_caller->bci());
caller.set_sp(_caller->sp());
// Copy out the standard machine state:
for (uint i = 0; i < TypeFunc::Parms; i++) {
caller.map()->set_req(i, ex_map->in(i));
}
if (ex_map->has_replaced_nodes()) {
_replaced_nodes_for_exceptions = true;
}
caller.map()->transfer_replaced_nodes_from(ex_map, _new_idx);
// ...and the exception:
Node* ex_oop = saved_ex_oop(ex_map);
SafePointNode* caller_ex_map = caller.make_exception_state(ex_oop);
// Finally, collect the new exception state in my exits:
_exits.add_exception_state(caller_ex_map);
}
//------------------------------do_exits---------------------------------------
void Parse::do_exits() {
set_parse_bci(InvocationEntryBci);
// Now peephole on the return bits
Node* region = _exits.control();
_exits.set_control(gvn().transform(region));
Node* iophi = _exits.i_o();
_exits.set_i_o(gvn().transform(iophi));
// Figure out if we need to emit the trailing barrier. The barrier is only
// needed in the constructors, and only in three cases:
//
// 1. The constructor wrote a final. The effects of all initializations
// must be committed to memory before any code after the constructor
// publishes the reference to the newly constructed object. Rather
// than wait for the publication, we simply block the writes here.
// Rather than put a barrier on only those writes which are required
// to complete, we force all writes to complete.
//
// 2. Experimental VM option is used to force the barrier if any field
// was written out in the constructor.
//
// 3. On processors which are not CPU_MULTI_COPY_ATOMIC (e.g. PPC64),
// support_IRIW_for_not_multiple_copy_atomic_cpu selects that
// MemBarVolatile is used before volatile load instead of after volatile
// store, so there's no barrier after the store.
// We want to guarantee the same behavior as on platforms with total store
// order, although this is not required by the Java memory model.
// In this case, we want to enforce visibility of volatile field
// initializations which are performed in constructors.
// So as with finals, we add a barrier here.
//
// "All bets are off" unless the first publication occurs after a
// normal return from the constructor. We do not attempt to detect
// such unusual early publications. But no barrier is needed on
// exceptional returns, since they cannot publish normally.
//
if (method()->is_initializer() &&
(wrote_final() ||
(AlwaysSafeConstructors && wrote_fields()) ||
(support_IRIW_for_not_multiple_copy_atomic_cpu && wrote_volatile()))) {