17
17
import com .oracle .truffle .api .source .SourceSection ;
18
18
import com .oracle .truffle .api .utilities .BranchProfile ;
19
19
import com .oracle .truffle .api .utilities .ConditionProfile ;
20
+ import org .jruby .truffle .nodes .RubyNode ;
20
21
import org .jruby .truffle .nodes .dispatch .CallDispatchHeadNode ;
22
+ import org .jruby .truffle .nodes .dispatch .DispatchHeadNode ;
21
23
import org .jruby .truffle .nodes .dispatch .DispatchHeadNodeFactory ;
22
24
import org .jruby .truffle .nodes .methods .UnsupportedOperationBehavior ;
23
25
import org .jruby .truffle .runtime .RubyContext ;
34
36
@ CoreClass (name = "Fixnum" )
35
37
public abstract class FixnumNodes {
36
38
39
+ private static final int BITS = 64 ;
40
+
37
41
@ CoreMethod (names = "-@" )
38
42
public abstract static class NegNode extends CoreMethodNode {
39
43
@@ -1275,21 +1279,26 @@ public Object bitXOr(long a, RubyBignum b) {
1275
1279
}
1276
1280
}
1277
1281
1278
- @ CoreMethod (names = "<<" , required = 1 , lowerFixnumParameters = 0 )
1282
+ @ CoreMethod (names = "<<" , required = 1 )
1279
1283
public abstract static class LeftShiftNode extends BignumNodes .BignumCoreMethodNode {
1280
1284
1285
+ @ Child private CallDispatchHeadNode fallbackCallNode ;
1286
+
1281
1287
public LeftShiftNode (RubyContext context , SourceSection sourceSection ) {
1282
1288
super (context , sourceSection );
1283
1289
}
1284
1290
1285
1291
public LeftShiftNode (LeftShiftNode prev ) {
1286
1292
super (prev );
1293
+ fallbackCallNode = prev .fallbackCallNode ;
1287
1294
}
1288
1295
1289
1296
protected Object lower (RubyBignum value ) {
1290
1297
return fixnumOrBignum (value );
1291
1298
}
1292
1299
1300
+ public abstract Object executeLeftShift (VirtualFrame frame , Object a , Object b );
1301
+
1293
1302
@ Specialization (guards = {"isPositive(arguments[1])" , "canShiftIntoInt" })
1294
1303
public int leftShift (int a , int b ) {
1295
1304
return a << b ;
@@ -1337,6 +1346,16 @@ public long leftShiftNeg(long a, int b) {
1337
1346
}
1338
1347
}
1339
1348
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
+
1340
1359
static boolean canShiftIntoInt (int a , int b ) {
1341
1360
return Integer .numberOfLeadingZeros (a ) - b > 0 ;
1342
1361
}
@@ -1359,46 +1378,65 @@ static boolean isStrictlyNegative(int value) {
1359
1378
1360
1379
}
1361
1380
1362
- @ CoreMethod (names = ">>" , required = 1 , lowerFixnumParameters = 0 )
1381
+ @ CoreMethod (names = ">>" , required = 1 )
1363
1382
public abstract static class RightShiftNode extends CoreMethodNode {
1364
1383
1365
- @ Child private CallDispatchHeadNode toInt ;
1384
+ @ Child private CallDispatchHeadNode fallbackCallNode ;
1385
+ @ Child private LeftShiftNode leftShiftNode ;
1366
1386
1367
1387
public RightShiftNode (RubyContext context , SourceSection sourceSection ) {
1368
1388
super (context , sourceSection );
1369
- toInt = DispatchHeadNodeFactory .createMethodCall (context );
1370
1389
}
1371
1390
1372
1391
public RightShiftNode (RightShiftNode prev ) {
1373
1392
super (prev );
1374
- toInt = prev .toInt ;
1393
+ fallbackCallNode = prev .fallbackCallNode ;
1394
+ leftShiftNode = prev .leftShiftNode ;
1375
1395
}
1376
1396
1377
1397
protected abstract Object executeRightShift (VirtualFrame frame , Object a , Object b );
1378
1398
1379
1399
@ Specialization
1380
- public int rightShift (int a , int b ) {
1400
+ public Object rightShift (VirtualFrame frame , int a , int b ) {
1381
1401
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
+ }
1386
1408
} 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 }));
1388
1415
}
1416
+
1417
+ return leftShiftNode .executeLeftShift (frame , a , -b );
1389
1418
}
1390
1419
}
1391
1420
1392
1421
@ Specialization
1393
- public long rightShift (long a , int b ) {
1422
+ public Object rightShift (VirtualFrame frame , long a , int b ) {
1394
1423
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
+ }
1399
1430
} 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 }));
1401
1437
}
1438
+
1439
+ return leftShiftNode .executeLeftShift (frame , a , -b );
1402
1440
}
1403
1441
}
1404
1442
@@ -1412,15 +1450,14 @@ public int rightShift(long a, RubyBignum b) {
1412
1450
return 0 ;
1413
1451
}
1414
1452
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 ));
1423
1458
}
1459
+
1460
+ return fallbackCallNode .call (frame , a , "right_shift_fallback" , null , b );
1424
1461
}
1425
1462
1426
1463
}
0 commit comments