Skip to content

Commit 47d566e

Browse files
committed
[Truffle] All Fixnum specs passing!
1 parent 2a87593 commit 47d566e

File tree

6 files changed

+129
-33
lines changed

6 files changed

+129
-33
lines changed

core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java

+62-25
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import com.oracle.truffle.api.source.SourceSection;
1818
import com.oracle.truffle.api.utilities.BranchProfile;
1919
import com.oracle.truffle.api.utilities.ConditionProfile;
20+
import org.jruby.truffle.nodes.RubyNode;
2021
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
22+
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
2123
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
2224
import org.jruby.truffle.nodes.methods.UnsupportedOperationBehavior;
2325
import org.jruby.truffle.runtime.RubyContext;
@@ -34,6 +36,8 @@
3436
@CoreClass(name = "Fixnum")
3537
public abstract class FixnumNodes {
3638

39+
private static final int BITS = 64;
40+
3741
@CoreMethod(names = "-@")
3842
public abstract static class NegNode extends CoreMethodNode {
3943

@@ -1275,21 +1279,26 @@ public Object bitXOr(long a, RubyBignum b) {
12751279
}
12761280
}
12771281

1278-
@CoreMethod(names = "<<", required = 1, lowerFixnumParameters = 0)
1282+
@CoreMethod(names = "<<", required = 1)
12791283
public abstract static class LeftShiftNode extends BignumNodes.BignumCoreMethodNode {
12801284

1285+
@Child private CallDispatchHeadNode fallbackCallNode;
1286+
12811287
public LeftShiftNode(RubyContext context, SourceSection sourceSection) {
12821288
super(context, sourceSection);
12831289
}
12841290

12851291
public LeftShiftNode(LeftShiftNode prev) {
12861292
super(prev);
1293+
fallbackCallNode = prev.fallbackCallNode;
12871294
}
12881295

12891296
protected Object lower(RubyBignum value) {
12901297
return fixnumOrBignum(value);
12911298
}
12921299

1300+
public abstract Object executeLeftShift(VirtualFrame frame, Object a, Object b);
1301+
12931302
@Specialization(guards = {"isPositive(arguments[1])", "canShiftIntoInt"})
12941303
public int leftShift(int a, int b) {
12951304
return a << b;
@@ -1337,6 +1346,16 @@ public long leftShiftNeg(long a, int b) {
13371346
}
13381347
}
13391348

1349+
@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])"})
1350+
public Object leftShiftFallback(VirtualFrame frame, Object a, Object b) {
1351+
if (fallbackCallNode == null) {
1352+
CompilerDirectives.transferToInterpreter();
1353+
fallbackCallNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
1354+
}
1355+
1356+
return fallbackCallNode.call(frame, a, "left_shift_fallback", null, b);
1357+
}
1358+
13401359
static boolean canShiftIntoInt(int a, int b) {
13411360
return Integer.numberOfLeadingZeros(a) - b > 0;
13421361
}
@@ -1359,46 +1378,65 @@ static boolean isStrictlyNegative(int value) {
13591378

13601379
}
13611380

1362-
@CoreMethod(names = ">>", required = 1, lowerFixnumParameters = 0)
1381+
@CoreMethod(names = ">>", required = 1)
13631382
public abstract static class RightShiftNode extends CoreMethodNode {
13641383

1365-
@Child private CallDispatchHeadNode toInt;
1384+
@Child private CallDispatchHeadNode fallbackCallNode;
1385+
@Child private LeftShiftNode leftShiftNode;
13661386

13671387
public RightShiftNode(RubyContext context, SourceSection sourceSection) {
13681388
super(context, sourceSection);
1369-
toInt = DispatchHeadNodeFactory.createMethodCall(context);
13701389
}
13711390

13721391
public RightShiftNode(RightShiftNode prev) {
13731392
super(prev);
1374-
toInt = prev.toInt;
1393+
fallbackCallNode = prev.fallbackCallNode;
1394+
leftShiftNode = prev.leftShiftNode;
13751395
}
13761396

13771397
protected abstract Object executeRightShift(VirtualFrame frame, Object a, Object b);
13781398

13791399
@Specialization
1380-
public int rightShift(int a, int b) {
1400+
public Object rightShift(VirtualFrame frame, int a, int b) {
13811401
if (b > 0) {
1382-
return a >> b;
1383-
} else {
1384-
if (-b >= Long.SIZE) {
1385-
return 0;
1402+
if (b >= BITS - 1) {
1403+
if (a < 0) {
1404+
return -1;
1405+
} else {
1406+
return 0;
1407+
}
13861408
} else {
1387-
return a << -b;
1409+
return a >> b;
1410+
}
1411+
} else {
1412+
if (leftShiftNode == null) {
1413+
CompilerDirectives.transferToInterpreter();
1414+
leftShiftNode = insert(FixnumNodesFactory.LeftShiftNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{null, null}));
13881415
}
1416+
1417+
return leftShiftNode.executeLeftShift(frame, a, -b);
13891418
}
13901419
}
13911420

13921421
@Specialization
1393-
public long rightShift(long a, int b) {
1422+
public Object rightShift(VirtualFrame frame, long a, int b) {
13941423
if (b > 0) {
1395-
return a >> b;
1396-
} else {
1397-
if (-b >= Long.SIZE) {
1398-
return 0;
1424+
if (b >= BITS - 1) {
1425+
if (a < 0) {
1426+
return -1;
1427+
} else {
1428+
return 0;
1429+
}
13991430
} else {
1400-
return a << -b;
1431+
return a >> b;
1432+
}
1433+
} else {
1434+
if (leftShiftNode == null) {
1435+
CompilerDirectives.transferToInterpreter();
1436+
leftShiftNode = insert(FixnumNodesFactory.LeftShiftNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{null, null}));
14011437
}
1438+
1439+
return leftShiftNode.executeLeftShift(frame, a, -b);
14021440
}
14031441
}
14041442

@@ -1412,15 +1450,14 @@ public int rightShift(long a, RubyBignum b) {
14121450
return 0;
14131451
}
14141452

1415-
@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])", "!isRubyBignum(arguments[1])"})
1416-
public Object rightShift(VirtualFrame frame, Object a, Object b) {
1417-
final Object coerced = toInt.call(frame, b, "to_int", null);
1418-
1419-
if (coerced instanceof Integer || coerced instanceof Long || coerced instanceof RubyBignum) {
1420-
return executeRightShift(frame, a, coerced);
1421-
} else {
1422-
throw new UnsupportedOperationException();
1453+
@Specialization(guards = {"!isInteger(arguments[1])", "!isLong(arguments[1])"})
1454+
public Object rightShiftFallback(VirtualFrame frame, Object a, Object b) {
1455+
if (fallbackCallNode == null) {
1456+
CompilerDirectives.transferToInterpreter();
1457+
fallbackCallNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
14231458
}
1459+
1460+
return fallbackCallNode.call(frame, a, "right_shift_fallback", null, b);
14241461
}
14251462

14261463
}

core/src/main/ruby/jruby/truffle/core.rb

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
require_relative 'core/thread'
1515
require_relative 'core/module'
1616
require_relative 'core/hash'
17+
require_relative 'core/fixnum'
1718

1819
require_relative 'core/rubinius/api/compat/type'
1920

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
2+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
3+
# redistribute it and/or modify it under the terms of the:
4+
#
5+
# Eclipse Public License version 1.0
6+
# GNU General Public License version 2
7+
# GNU Lesser General Public License version 2.1
8+
9+
# Copyright (c) 2007-2014, Evan Phoenix and contributors
10+
# All rights reserved.
11+
#
12+
# Redistribution and use in source and binary forms, with or without
13+
# modification, are permitted provided that the following conditions are met:
14+
#
15+
# * Redistributions of source code must retain the above copyright notice, this
16+
# list of conditions and the following disclaimer.
17+
# * Redistributions in binary form must reproduce the above copyright notice
18+
# this list of conditions and the following disclaimer in the documentation
19+
# and/or other materials provided with the distribution.
20+
# * Neither the name of Rubinius nor the names of its contributors
21+
# may be used to endorse or promote products derived from this software
22+
# without specific prior written permission.
23+
#
24+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34+
35+
class Fixnum
36+
37+
def left_shift_fallback(other)
38+
# Fallback from Rubinius' Fixnum#<<, after the primitive call
39+
40+
other = Rubinius::Type.coerce_to other, Integer, :to_int
41+
unless other.kind_of? Fixnum
42+
raise RangeError, "argument is out of range for a Fixnum"
43+
end
44+
45+
self << other
46+
end
47+
48+
private :left_shift_fallback
49+
50+
def right_shift_fallback(other)
51+
# Fallback from Rubinius' Fixnum#>>, after the primitive call
52+
53+
other = Rubinius::Type.coerce_to other, Integer, :to_int
54+
unless other.kind_of? Fixnum
55+
raise RangeError, "argument is out of range for a Fixnum"
56+
end
57+
58+
self >> other
59+
end
60+
61+
private :right_shift_fallback
62+
63+
end

core/src/main/ruby/jruby/truffle/core/rubinius/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ of Rubinius. This code was written by Evan Phoenix, Brian Shirai, et al.
44

55
https://github.com/rubinius/rubinius
66

7+
Some files in the parent directory contain small snippets of code from the same
8+
repository. These are individually annotated.
9+
710
`api` contains code from `rubinius-core-api`, the Rubinius API implementation
811
written in Ruby, in some cases modified. We have taken files from commit
912
8d01207061518355da9b53274fe8766ecf85fdfe. This code was written by Evan Phoenix,

spec/truffle/tags/core/fixnum/left_shift_tags.txt

-2
This file was deleted.

spec/truffle/tags/core/fixnum/right_shift_tags.txt

-6
This file was deleted.

0 commit comments

Comments
 (0)