RFR: 8256385: C2: fatal error: modified node is not on IGVN._worklist

Roland Westrelin roland at openjdk.java.net
Tue Nov 17 09:13:03 UTC 2020


On Tue, 17 Nov 2020 09:00:50 GMT, Christian Hagedorn <chagedorn at openjdk.org> wrote:

>> `PhaseIdealLoop::find_safepoint` creates a temporary MergeMemNode that is not removed if we bail out from the optimization early (see `return NULL` statements). The fix is to simply add the MergeMem to the worklist to make sure it is always reclaimed by IGVN.
>> 
>> Interestingly this code path was not triggered by any of our tests but only with a test case generated by the Java Fuzzer. I've added a simplified version of that test case.
>> 
>> Thanks,
>> Tobias
>
> Looks good to me.

There's a call to _igvn.remove_dead_node(mm) below but the problem is that it's not always reached. I hit a similar problem while reworking the long counted loop support and fixed it by refactoring the code to:

    
  MergeMemNode* mm = NULL;
#ifdef ASSERT
    if (mem->is_MergeMem()) {
      mm = mem->clone()->as_MergeMem();
      for (MergeMemStream mms(mem->as_MergeMem()); mms.next_non_empty(); ) {
        if (mms.alias_idx() != Compile::AliasIdxBot && loop != get_loop(ctrl_or_self(mms.memory()))) {
          mm->set_memory_at(mms.alias_idx(), mem->as_MergeMem()->base_memory());
        }
      }
    }
#endif
    if (!no_side_effect_since_safepoint(C, x, mem, mm)) {
      safepoint = NULL;
    } else {
      assert(mm == NULL|| _igvn.transform(mm) == mem->as_MergeMem()->base_memory(), "all memory state should have been processed");
    }
#ifdef ASSERT
    if (mm != NULL) {
      _igvn.remove_dead_node(mm);
    }
#endif
with a new method:
static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, MergeMemNode* mm) {
  SafePointNode* safepoint = NULL;
  for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) {
    Node* u = x->fast_out(i);
    if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {
      Node* m = u->in(LoopNode::LoopBackControl);
      if (u->adr_type() == TypePtr::BOTTOM) {
        if (m->is_MergeMem() && mem->is_MergeMem()) {
          if (m != mem DEBUG_ONLY(|| true)) {
            for (MergeMemStream mms(m->as_MergeMem(), mem->as_MergeMem()); mms.next_non_empty2(); ) {
              if (!mms.is_empty()) {
                if (mms.memory() != mms.memory2()) {
                  return false;
                }
#ifdef ASSERT
                if (mms.alias_idx() != Compile::AliasIdxBot) {
                  mm->set_memory_at(mms.alias_idx(), mem->as_MergeMem()->base_memory());
                }
#endif
              } 
            }
          }
        } else if (mem->is_MergeMem()) {
          if (m != mem->as_MergeMem()->base_memory()) {
            return false;
          }
        } else {
          return false;
        }
      } else {
        if (mem->is_MergeMem()) {
          if (m != mem->as_MergeMem()->memory_at(C->get_alias_index(u->adr_type()))) {
            return false;
          }
#ifdef ASSERT
          mm->set_memory_at(C->get_alias_index(u->adr_type()), mem->as_MergeMem()->base_memory());
#endif
        } else {
          if (m != mem) {
            return false;
          }
        }
      }
    }
  }
  return true;
}

-------------

PR: https://git.openjdk.java.net/jdk/pull/1252


More information about the hotspot-compiler-dev mailing list