Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d0a0c2d39f8d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3af5d2327683
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Dec 1, 2014

  1. Copy the full SHA
    775b98c View commit details
  2. [Truffle] Fix object_id for large Fixnum and implement it for Float.

    * MRI has a similar case for Fixnum larger than 2^61-1 or smaller than -2^61.
    eregon committed Dec 1, 2014
    Copy the full SHA
    3af5d23 View commit details
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import java.util.*;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.ExactMath;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -95,25 +96,48 @@ public int objectIDFalse(boolean value) {

@Specialization
public long objectID(int value) {
return ObjectIDOperations.fixnumToID(value);
return ObjectIDOperations.smallFixnumToID(value);
}

@Specialization(rewriteOn = ArithmeticException.class)
public long objectIDSmallFixnumOverflow(long value) {
return ObjectIDOperations.smallFixnumToIDOverflow(value);
}

/* TODO: Ideally we would have this instead of the code below to speculate better. [GRAAL-903]
@Specialization(guards = "isSmallFixnum")
public long objectIDSmallFixnum(long value) {
return ObjectIDOperations.smallFixnumToID(value);
}
@Specialization(guards = "!isSmallFixnum")
public Object objectIDLargeFixnum(long value) {
return ObjectIDOperations.largeFixnumToID(getContext(), value);
} */

@Specialization
public long objectID(long value) {
return ObjectIDOperations.fixnumToID(value);
public Object objectID(long value) {
if (isSmallFixnum(value)) {
return ObjectIDOperations.smallFixnumToID(value);
} else {
return ObjectIDOperations.largeFixnumToID(getContext(), value);
}
}

@Specialization
public long objectID(double value) {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException("No ID for Float yet");
public RubyBignum objectID(double value) {
return ObjectIDOperations.floatToID(getContext(), value);
}

@Specialization
public long objectID(RubyBasicObject object) {
return object.getObjectID();
}

protected boolean isSmallFixnum(long fixnum) {
return ObjectIDOperations.isSmallFixnum(fixnum);
}

}

@CoreMethod(names = {"equal?", "=="}, required = 1)
Original file line number Diff line number Diff line change
@@ -377,6 +377,11 @@ public RubyClass getClass(@SuppressWarnings("unused") int value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
public RubyClass getClass(@SuppressWarnings("unused") long value) {
return getContext().getCoreLibrary().getFixnumClass();
}

@Specialization
public RubyClass getClass(@SuppressWarnings("unused") RubyBignum value) {
return getContext().getCoreLibrary().getBignumClass();
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ public Object id2Ref(long id) {
return true;
} else if (id == ObjectIDOperations.FALSE) {
return false;
} else if (ObjectIDOperations.isFixnum(id)) {
} else if (ObjectIDOperations.isSmallFixnumID(id)) {
return ObjectIDOperations.toFixnum(id);
} else {
final Object object = getContext().getObjectSpaceManager().collectLiveObjects().get(id);
@@ -57,7 +57,24 @@ public Object id2Ref(long id) {
return object;
}
}
}

@Specialization(guards = "isLargeFixnumID")
public Object id2RefLargeFixnum(RubyBignum id) {
return ObjectIDOperations.toFixnum(id);
}

@Specialization(guards = "isFloatID")
public double id2RefFloat(RubyBignum id) {
return ObjectIDOperations.toFloat(id);
}

protected boolean isLargeFixnumID(RubyBignum id) {
return ObjectIDOperations.isLargeFixnumID(id);
}

protected boolean isFloatID(RubyBignum id) {
return ObjectIDOperations.isFloatID(id);
}

}
Original file line number Diff line number Diff line change
@@ -9,21 +9,94 @@
*/
package org.jruby.truffle.runtime;

import com.oracle.truffle.api.ExactMath;
import org.jruby.truffle.runtime.core.RubyBignum;

import java.math.BigInteger;

/**
* <pre>
* Object IDs distribution
*
* We try to respect MRI scheme when it makes sense (Fixnum for the moment).
* Have a look at include/ruby/ruby.h below ruby_special_consts.
*
* Encoding for Fixnum (long):
* ... 0000 = false
* ... 0010 = true
* ... 0100 = nil
*
* ... xxx1 = Fixnum of value (id-1)/2 if -2^62 <= value < 2^62
* ... xxx0 = BasicObject generated id (for id > 4)
*
* Encoding for Bignum:
* ... 0001 | 64-bit long = Fixnum if value < -2^62 or value >= 2^62
* ... 0010 | 64-bit raw double bits = Float
* </pre>
*/
public abstract class ObjectIDOperations {

public static int FALSE = 0;
public static int TRUE = 1;
public static int TRUE = 2;
public static int NIL = 4;
public static int FIRST_OBJECT_ID = 6;

private static BigInteger LARGE_FIXNUM_FLAG = BigInteger.ONE.shiftLeft(64);
private static BigInteger FLOAT_FLAG = BigInteger.ONE.shiftLeft(65);

private static long SMALL_FIXNUM_MIN = -(1L << 62);
private static long SMALL_FIXNUM_MAX = (1L << 62) - 1;

// primitive => ID

public static boolean isSmallFixnum(long fixnum) {
// TODO: optimize
return SMALL_FIXNUM_MIN <= fixnum && fixnum <= SMALL_FIXNUM_MAX;
}

public static long smallFixnumToIDOverflow(long fixnum) throws ArithmeticException{
return ExactMath.addExact(ExactMath.multiplyExact(fixnum, 2), 1);
}

public static long smallFixnumToID(long fixnum) {
assert isSmallFixnum(fixnum);
return fixnum * 2 + 1;
}

public static RubyBignum largeFixnumToID(RubyContext context, long fixnum) {
assert !isSmallFixnum(fixnum);
return new RubyBignum(context.getCoreLibrary().getBignumClass(), BigInteger.valueOf(fixnum).or(LARGE_FIXNUM_FLAG));
}

public static boolean isFixnum(long id) {
public static RubyBignum floatToID(RubyContext context, double value) {
long bits = Double.doubleToRawLongBits(value);
return new RubyBignum(context.getCoreLibrary().getBignumClass(), BigInteger.valueOf(bits).or(FLOAT_FLAG));
}

// ID => primitive

public static boolean isSmallFixnumID(long id) {
return id % 2 != 0;
}

public static long toFixnum(long id) {
return (id - 1) / 2;
}

public static long fixnumToID(long fixnum) {
return fixnum * 2 + 1;
public static boolean isLargeFixnumID(RubyBignum id) {
return !id.bigIntegerValue().and(LARGE_FIXNUM_FLAG).equals(BigInteger.ZERO);
}

public static long toFixnum(RubyBignum id) {
return id.longValue();
}

public static boolean isFloatID(RubyBignum id) {
return !id.bigIntegerValue().and(FLOAT_FLAG).equals(BigInteger.ZERO);
}

public static double toFloat(RubyBignum id) {
return Double.longBitsToDouble(id.longValue());
}

}
Original file line number Diff line number Diff line change
@@ -34,10 +34,8 @@
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.truffle.runtime.core.RubyException;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
import org.jruby.truffle.runtime.core.RubyThread;
import org.jruby.truffle.runtime.subsystems.*;
import org.jruby.truffle.runtime.util.Supplier;
import org.jruby.truffle.translator.TranslatorDriver;
@@ -66,7 +64,7 @@ public class RubyContext extends ExecutionContext {

private SourceCallback sourceCallback = null;

private final AtomicLong nextObjectID = new AtomicLong(6);
private final AtomicLong nextObjectID = new AtomicLong(ObjectIDOperations.FIRST_OBJECT_ID);

private final ThreadLocal<Queue<Object>> throwTags = new ThreadLocal<Queue<Object>>() {