@@ -396,6 +396,10 @@ void Compile::remove_useless_node(Node* dead) {
396
396
remove_useless_late_inlines ( &_string_late_inlines, dead);
397
397
remove_useless_late_inlines ( &_boxing_late_inlines, dead);
398
398
remove_useless_late_inlines (&_vector_reboxing_late_inlines, dead);
399
+
400
+ if (dead->is_CallStaticJava ()) {
401
+ remove_unstable_if_trap (dead->as_CallStaticJava (), false );
402
+ }
399
403
}
400
404
BarrierSetC2* bs = BarrierSet::barrier_set ()->barrier_set_c2 ();
401
405
bs->unregister_potential_barrier_node (dead);
@@ -434,6 +438,7 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
434
438
remove_useless_nodes (_skeleton_predicate_opaqs, useful);
435
439
remove_useless_nodes (_expensive_nodes, useful); // remove useless expensive nodes
436
440
remove_useless_nodes (_for_post_loop_igvn, useful); // remove useless node recorded for post loop opts IGVN pass
441
+ remove_useless_unstable_if_traps (useful); // remove useless unstable_if traps
437
442
remove_useless_coarsened_locks (useful); // remove useless coarsened locks nodes
438
443
439
444
BarrierSetC2* bs = BarrierSet::barrier_set ()->barrier_set_c2 ();
@@ -607,6 +612,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
607
612
_skeleton_predicate_opaqs (comp_arena(), 8, 0, NULL),
608
613
_expensive_nodes (comp_arena(), 8, 0, NULL),
609
614
_for_post_loop_igvn(comp_arena(), 8, 0, NULL),
615
+ _unstable_if_traps (comp_arena(), 8, 0, NULL),
610
616
_coarsened_locks (comp_arena(), 8, 0, NULL),
611
617
_congraph(NULL ),
612
618
NOT_PRODUCT(_igv_printer(NULL ) COMMA)
@@ -1854,6 +1860,106 @@ void Compile::process_for_post_loop_opts_igvn(PhaseIterGVN& igvn) {
1854
1860
}
1855
1861
}
1856
1862
1863
+ void Compile::record_unstable_if_trap (UnstableIfTrap* trap) {
1864
+ if (OptimizeUnstableIf) {
1865
+ _unstable_if_traps.append (trap);
1866
+ }
1867
+ }
1868
+
1869
+ void Compile::remove_useless_unstable_if_traps (Unique_Node_List& useful) {
1870
+ for (int i = _unstable_if_traps.length () - 1 ; i >= 0 ; i--) {
1871
+ UnstableIfTrap* trap = _unstable_if_traps.at (i);
1872
+ Node* n = trap->uncommon_trap ();
1873
+ if (!useful.member (n)) {
1874
+ _unstable_if_traps.delete_at (i); // replaces i-th with last element which is known to be useful (already processed)
1875
+ }
1876
+ }
1877
+ }
1878
+
1879
+ // Remove the unstable if trap associated with 'unc' from candidates. It is either dead
1880
+ // or fold-compares case. Return true if succeed or not found.
1881
+ //
1882
+ // In rare cases, the found trap has been processed. It is too late to delete it. Return
1883
+ // false and ask fold-compares to yield.
1884
+ //
1885
+ // 'fold-compares' may use the uncommon_trap of the dominating IfNode to cover the fused
1886
+ // IfNode. This breaks the unstable_if trap invariant: control takes the unstable path
1887
+ // when deoptimization does happen.
1888
+ bool Compile::remove_unstable_if_trap (CallStaticJavaNode* unc, bool yield) {
1889
+ for (int i = 0 ; i < _unstable_if_traps.length (); ++i) {
1890
+ UnstableIfTrap* trap = _unstable_if_traps.at (i);
1891
+ if (trap->uncommon_trap () == unc) {
1892
+ if (yield && trap->modified ()) {
1893
+ return false ;
1894
+ }
1895
+ _unstable_if_traps.delete_at (i);
1896
+ break ;
1897
+ }
1898
+ }
1899
+ return true ;
1900
+ }
1901
+
1902
+ // Re-calculate unstable_if traps with the liveness of next_bci, which points to the unlikely path.
1903
+ // It needs to be done after igvn because fold-compares may fuse uncommon_traps and before renumbering.
1904
+ void Compile::process_for_unstable_if_traps (PhaseIterGVN& igvn) {
1905
+ for (int i = _unstable_if_traps.length () - 1 ; i >= 0 ; --i) {
1906
+ UnstableIfTrap* trap = _unstable_if_traps.at (i);
1907
+ CallStaticJavaNode* unc = trap->uncommon_trap ();
1908
+ int next_bci = trap->next_bci ();
1909
+ bool modified = trap->modified ();
1910
+
1911
+ if (next_bci != -1 && !modified) {
1912
+ assert (!_dead_node_list.test (unc->_idx ), " changing a dead node!" );
1913
+ JVMState* jvms = unc->jvms ();
1914
+ ciMethod* method = jvms->method ();
1915
+ ciBytecodeStream iter (method);
1916
+
1917
+ iter.force_bci (jvms->bci ());
1918
+ assert (next_bci == iter.next_bci () || next_bci == iter.get_dest (), " wrong next_bci at unstable_if" );
1919
+ Bytecodes::Code c = iter.cur_bc ();
1920
+ Node* lhs = nullptr ;
1921
+ Node* rhs = nullptr ;
1922
+ if (c == Bytecodes::_if_acmpeq || c == Bytecodes::_if_acmpne) {
1923
+ lhs = unc->peek_operand (0 );
1924
+ rhs = unc->peek_operand (1 );
1925
+ } else if (c == Bytecodes::_ifnull || c == Bytecodes::_ifnonnull) {
1926
+ lhs = unc->peek_operand (0 );
1927
+ }
1928
+
1929
+ ResourceMark rm;
1930
+ const MethodLivenessResult& live_locals = method->liveness_at_bci (next_bci);
1931
+ assert (live_locals.is_valid (), " broken liveness info" );
1932
+ int len = (int )live_locals.size ();
1933
+
1934
+ for (int i = 0 ; i < len; i++) {
1935
+ Node* local = unc->local (jvms, i);
1936
+ // kill local using the liveness of next_bci.
1937
+ // give up when the local looks like an operand to secure reexecution.
1938
+ if (!live_locals.at (i) && !local->is_top () && local != lhs && local!= rhs) {
1939
+ uint idx = jvms->locoff () + i;
1940
+ #ifdef ASSERT
1941
+ if (Verbose) {
1942
+ tty->print (" [unstable_if] kill local#%d: " , idx);
1943
+ local->dump ();
1944
+ tty->cr ();
1945
+ }
1946
+ #endif
1947
+ igvn.replace_input_of (unc, idx, top ());
1948
+ modified = true ;
1949
+ }
1950
+ }
1951
+ }
1952
+
1953
+ // keep the mondified trap for late query
1954
+ if (modified) {
1955
+ trap->set_modified ();
1956
+ } else {
1957
+ _unstable_if_traps.delete_at (i);
1958
+ }
1959
+ }
1960
+ igvn.optimize ();
1961
+ }
1962
+
1857
1963
// StringOpts and late inlining of string methods
1858
1964
void Compile::inline_string_calls (bool parse_time) {
1859
1965
{
@@ -2138,6 +2244,8 @@ void Compile::Optimize() {
2138
2244
2139
2245
print_method (PHASE_ITER_GVN1, 2 );
2140
2246
2247
+ process_for_unstable_if_traps (igvn);
2248
+
2141
2249
inline_incrementally (igvn);
2142
2250
2143
2251
print_method (PHASE_INCREMENTAL_INLINE, 2 );
0 commit comments