Skip to content

Commit

Permalink
[Truffle] Implement Fixnum#<<(int) correctly.
Browse files Browse the repository at this point in the history
* Mostly, there was no case to return an int.
  • Loading branch information
eregon committed Oct 30, 2014
1 parent 816e3e2 commit 52de8f1
Showing 1 changed file with 43 additions and 7 deletions.
50 changes: 43 additions & 7 deletions core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
Expand Up @@ -1187,21 +1187,49 @@ public LeftShiftNode(LeftShiftNode prev) {
fixnumOrBignum = prev.fixnumOrBignum;
}

@Specialization
public Object leftShift(int a, int b) {
return leftShift((long) a, b);
@Specialization(guards = "canShiftIntoInt")
public int leftShift(int a, int b) {
if (b > 0) {
bAboveZeroProfile.enter();

return a << b;
} else {
bNotAboveZeroProfile.enter();
if (-b >= Integer.SIZE) {
return 0;
} else {
return a >> -b;
}
}
}

@Specialization(guards = "canShiftIntoLong")
public long leftShift(long a, int b) {
if (b > 0) {
bAboveZeroProfile.enter();

return a << b;
} else {
bNotAboveZeroProfile.enter();

if (-b >= Long.SIZE) {
return 0;
} else {
return a >> -b;
}
}
}

@Specialization
public Object leftShift(long a, int b) {
public Object leftShiftWithOverflow(long a, int b) {
if (b > 0) {
bAboveZeroProfile.enter();

if (Long.SIZE - Long.numberOfLeadingZeros(a) + b > Long.SIZE - 1) {
if (canShiftIntoLong(a, b)) {
return a << b;
} else {
useBignumProfile.enter();
return fixnumOrBignum.fixnumOrBignum(SlowPathBigInteger.shiftLeft(BigInteger.valueOf(a), b));
} else {
return a << b;
}
} else {
bNotAboveZeroProfile.enter();
Expand All @@ -1214,6 +1242,14 @@ public Object leftShift(long a, int b) {
}
}

static boolean canShiftIntoInt(int a, int b) {
return Integer.numberOfLeadingZeros(a) - b > 0;
}

static boolean canShiftIntoLong(long a, int b) {
return Long.numberOfLeadingZeros(a) - b > 0;
}

}

@CoreMethod(names = ">>", required = 1, lowerFixnumParameters = 0)
Expand Down

0 comments on commit 52de8f1

Please sign in to comment.