Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Truffle] Refactor Fixnum#<<.
  • Loading branch information
eregon committed Nov 6, 2014
1 parent 2a04675 commit 7765d78
Showing 1 changed file with 49 additions and 48 deletions.
97 changes: 49 additions & 48 deletions core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
Expand Up @@ -1098,88 +1098,89 @@ public abstract static class LeftShiftNode extends CoreMethodNode {

@Child protected FixnumOrBignumNode fixnumOrBignum;

private final BranchProfile bAboveZeroProfile = new BranchProfile();
private final BranchProfile bNotAboveZeroProfile = new BranchProfile();
private final BranchProfile useBignumProfile = new BranchProfile();

public LeftShiftNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
fixnumOrBignum = new FixnumOrBignumNode();
}

public LeftShiftNode(LeftShiftNode prev) {
super(prev);
fixnumOrBignum = prev.fixnumOrBignum;
}

@Specialization(guards = "canShiftIntoInt")
protected Object lower(BigInteger value) {
if (fixnumOrBignum == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
fixnumOrBignum = insert(new FixnumOrBignumNode());
}
return fixnumOrBignum.fixnumOrBignum(value);
}

@Specialization(guards = {"isPositive(arguments[1])", "canShiftIntoInt"})
public int leftShift(int a, int b) {
if (b > 0) {
bAboveZeroProfile.enter();
return a << b;
}

return a << b;
} else {
bNotAboveZeroProfile.enter();
if (-b >= Integer.SIZE) {
return 0;
} else {
return a >> -b;
}
}
@Specialization(guards = {"isPositive(arguments[1])", "canShiftIntoLong"})
public long leftShiftToLong(int a, int b) {
return leftShiftToLong((long) a, b);
}

@Specialization
@Specialization(guards = {"isPositive(arguments[1])"})
public Object leftShiftWithOverflow(int a, int b) {
return leftShiftWithOverflow((long) a, b);
}

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

return a << b;
@Specialization(guards = "isStrictlyNegative(arguments[1])")
public int leftShiftNeg(int a, int b) {
if (-b >= Integer.SIZE) {
return 0;
} else {
bNotAboveZeroProfile.enter();

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

@Specialization
public Object leftShiftWithOverflow(long a, int b) {
if (b > 0) {
bAboveZeroProfile.enter();
@Specialization(guards = {"isPositive(arguments[1])", "canShiftIntoLong"})
public long leftShiftToLong(long a, int b) {
return a << b;
}

if (canShiftIntoLong(a, b)) {
return a << b;
} else {
useBignumProfile.enter();
return fixnumOrBignum.fixnumOrBignum(SlowPathBigInteger.shiftLeft(BigInteger.valueOf(a), b));
}
@Specialization(guards = {"isPositive(arguments[1])"})
public Object leftShiftWithOverflow(long a, int b) {
if (canShiftIntoLong(a, b)) {
return leftShiftToLong(a, b);
} else {
bNotAboveZeroProfile.enter();
return lower(SlowPathBigInteger.shiftLeft(BigInteger.valueOf(a), b));
}
}

if (-b >= Long.SIZE) {
return 0;
} else {
return a >> -b;
}
@Specialization(guards = "isStrictlyNegative(arguments[1])")
public long leftShiftNeg(long a, int b) {
if (-b >= Integer.SIZE) {
return 0;
} else {
return a >> -b;
}
}

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

static boolean canShiftIntoLong(int a, int b) {
return canShiftIntoLong((long) a, b);
}

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

static boolean isPositive(int value) {
return value >= 0;
}

static boolean isStrictlyNegative(int value) {
return value < 0;
}

}

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

0 comments on commit 7765d78

Please sign in to comment.