/** * 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; }