Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8333722

Fix CompilerDirectives for non-compiler JVM variants

XMLWordPrintable

    • b02
    • generic
    • generic

        `DirectivesStack::getMatchingDirective()` relies on the fact that the default directives set is always enabled. And that's indeed the case for normal builds with C1 and C2 compilers (see `DirectivesStack::init()` in `compilerDirectives.cpp`):

        ```
        // Create a new dirstack and push a default directive
        void DirectivesStack::init() {
          CompilerDirectives* _default_directives = new CompilerDirectives();
          char str[] = "*.*";
          const char* error_msg = nullptr;
          _default_directives->add_match(str, error_msg);
        #if defined(COMPILER1) || INCLUDE_JVMCI
          _default_directives->_c1_store->EnableOption = true;
        #endif
        #ifdef COMPILER2
          if (CompilerConfig::is_c2_enabled()) {
            _default_directives->_c2_store->EnableOption = true;
          }
        #endif
          assert(error_msg == nullptr, "Must succeed.");
          push(_default_directives);
        }
        ```

        However, if we're building a JVM configuration without compilers (e.g. `--with-jvm-variants=core`), this is not the case and `DirectivesStack::getMatchingDirective()` will return the base directive set without incrementing the reference count of its directive:

        ```
            CompilerDirectives* dir = _top;
            assert(dir != nullptr, "Must be initialized");

            while (dir != nullptr) {
              if (dir->is_default_directive() || dir->match(method)) {
                match = dir->get_for(comp);
                assert(match != nullptr, "Consistency");
                if (match->EnableOption) {
                  // The directiveSet for this compile is also enabled -> success
                  dir->inc_refcount();
                  break;
                }
              }
              dir = dir->next();
            }
          }
          guarantee(match != nullptr, "There should always be a default directive that matches");

          // Check for legacy compile commands update, without DirectivesStack_lock
          return match->compilecommand_compatibility_init(method);
        ```

        If this directive set will be released, it will delete the corresponding base directive and subsequent usages of the base directive will lead to a segmentation fault.

        After [JDK-8329421: Native methods can not be selectively printed](https://bugs.openjdk.org/browse/JDK-8329421) which replaced the call to
        ```
        DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
        ```
        by
        ```
        DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, CompileBroker::compiler(CompLevel_simple));
        ```
        in `sharedRuntime.cpp` this issue is now triggered at JVM startup for non-compiler configurations when native wrappers are generated (see https://github.com/openjdk/jdk/pull/18567#issuecomment-2149408243).

        The fix is trivial. Just increment the reference count of a compiler directive in `DirectivesStack::getMatchingDirective()` if it is the base directive, even if it is not enabled.

              simonis Volker Simonis
              simonis Volker Simonis
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: