text: /*
   * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. This
   * code is released under a tri EPL/GPL/LGPL license. You can use it,
   * redistribute it and/or modify it under the terms of the:
   *
   * Eclipse Public License version 2.0, or
   * GNU General Public License version 2, or
   * GNU Lesser General Public License version 2.1.
   */
  package org.truffleruby.language.objects;
  
  import org.truffleruby.RubyLanguage;
  import org.truffleruby.core.klass.RubyClass;
  import org.truffleruby.core.module.ModuleOperations;
  import org.truffleruby.core.module.RubyModule;
  import org.truffleruby.language.RubyBaseNode;
  
  import com.oracle.truffle.api.Assumption;
  import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
  import com.oracle.truffle.api.dsl.Cached;
  import com.oracle.truffle.api.dsl.GenerateUncached;
  import com.oracle.truffle.api.dsl.ReportPolymorphism;
  import com.oracle.truffle.api.dsl.Specialization;
  
  @ReportPolymorphism
  @GenerateUncached
  public abstract class IsANode extends RubyBaseNode {
  
      public static IsANode create() {
          return IsANodeGen.create();
      }
  
      public abstract boolean executeIsA(Object self, RubyModule module);
  
      @Specialization(
              guards = {
                      "metaClassNode.execute(self) == cachedMetaClass",
                      "module == cachedModule" },
              assumptions = "getHierarchyUnmodifiedAssumption(cachedModule)",
              limit = "getCacheLimit()")
      protected boolean isACached(Object self, RubyModule module,
              @Cached MetaClassNode metaClassNode,
              @Cached("metaClassNode.execute(self)") RubyClass cachedMetaClass,
              @Cached("module") RubyModule cachedModule,
              @Cached("isA(cachedMetaClass, cachedModule)") boolean result) {
          return result;
      }
  
      public Assumption getHierarchyUnmodifiedAssumption(RubyModule module) {
          return module.fields.getHierarchyUnmodifiedAssumption();
      }
  
      @Specialization(replaces = "isACached")
      protected boolean isAUncached(Object self, RubyModule module,
              @Cached MetaClassNode metaClassNode) {
          return isA(metaClassNode.execute(self), module);
      }
  
      @TruffleBoundary
      protected boolean isA(RubyClass metaClass, RubyModule module) {
          return ModuleOperations.assignableTo(metaClass, module);
      }
  
      protected int getCacheLimit() {
          return RubyLanguage.getCurrentContext().getOptions().IS_A_CACHE;
      }
  
  }
  