Example #1
0
  /**
   * Retrieves the Handle object associated with a {@link RubyObject}. Retrieval is either done
   * through the {@link GC} for Handles that have already been created, or depending on the object's
   * native class index.<br>
   * Fixnum's and Symbol's native Handles are created through bit-shifting on their values, File and
   * Float Handles are created using special JNI methods. All other objects are passed to the
   * generic {@link Native#newHandle} method.<br>
   * Once a Handle has been created, it is registered with the {@link GC} to prevent
   * garbage-collection during native method runs.
   */
  static Handle valueOf(IRubyObject obj) {
    Handle h = GC.lookup(obj);
    if (h != null) {
      return h;
    }

    Ruby runtime = obj.getRuntime();
    long nativeHandle;

    if (obj instanceof RubyObject) {
      int type = ((RubyObject) obj).getNativeTypeIndex();
      switch (type) {
        case ClassIndex.FIXNUM:
          {
            final long val = ((RubyFixnum) obj).getLongValue();
            nativeHandle =
                (val <= FIXNUM_MAX && val >= FIXNUM_MIN)
                    ? ((val << FIXNUM_SHIFT) | FIXNUM_FLAG)
                    : Native.getInstance(runtime).newFixnumHandle(obj, val);
          }
          break;

        case ClassIndex.FLOAT:
          nativeHandle =
              Native.getInstance(runtime).newFloatHandle(obj, ((RubyNumeric) obj).getDoubleValue());
          break;

        case ClassIndex.SYMBOL:
          nativeHandle = ((long) ((RubySymbol) obj).getId() << SYMBOL_SHIFT) | SYMBOL_FLAG;
          break;

        case ClassIndex.FILE: // RubyIO uses FILE as type index, matching MRI's T_FILE
          nativeHandle =
              Native.getInstance(runtime)
                  .newIOHandle(
                      obj,
                      (int) ((RubyIO) obj).fileno(runtime.getCurrentContext()).getLongValue(),
                      ((RubyIO) obj).getOpenFile().getMode());
          break;

        default:
          nativeHandle = Native.getInstance(runtime).newHandle(obj, type);
          break;
      }
    } else {
      nativeHandle = Native.getInstance(runtime).newHandle(obj, ClassIndex.OBJECT);
    }

    Handle handle = newHandle(runtime, obj, nativeHandle);

    GC.register(obj, handle);

    return handle;
  }