|
79 | 79 | import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
|
80 | 80 |
|
81 | 81 | import java.math.BigInteger;
|
82 |
| -import java.util.Arrays; |
83 | 82 | import java.util.List;
|
84 | 83 |
|
85 | 84 | import com.oracle.graal.python.PythonLanguage;
|
|
105 | 104 | import com.oracle.graal.python.builtins.objects.type.slots.TpSlotLen.LenBuiltinNode;
|
106 | 105 | import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSetAttr.SetAttrBuiltinNode;
|
107 | 106 | import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSizeArgFun.SqItemBuiltinNode;
|
| 107 | +import com.oracle.graal.python.lib.PyNumberAddNode; |
108 | 108 | import com.oracle.graal.python.lib.PyNumberAsSizeNode;
|
109 | 109 | import com.oracle.graal.python.lib.PyObjectReprAsTruffleStringNode;
|
110 | 110 | import com.oracle.graal.python.lib.PyObjectRichCompareBool;
|
@@ -279,6 +279,8 @@ static int len(Object self,
|
279 | 279 | }
|
280 | 280 | }
|
281 | 281 |
|
| 282 | + // TODO: remove once all dunder methods are converted to slots and to |
| 283 | + // NormalizeForeignForBinopNode |
282 | 284 | abstract static class ForeignBinaryNode extends BinaryOpBuiltinNode {
|
283 | 285 | @Child private BinaryOpNode op;
|
284 | 286 | protected final boolean reverse;
|
@@ -408,36 +410,134 @@ public static PNotImplemented doGeneric(Object left, Object right) {
|
408 | 410 | }
|
409 | 411 | }
|
410 | 412 |
|
411 |
| - @Slot(value = SlotKind.nb_add, isComplex = true) |
412 |
| - @GenerateNodeFactory |
413 |
| - abstract static class AddNode extends ForeignBinaryNode { |
414 |
| - AddNode() { |
415 |
| - super(BinaryArithmetic.Add.create(), false); |
| 413 | + @GenerateInline |
| 414 | + @GenerateCached(false) |
| 415 | + abstract static class NormalizeForeignForBinopNode extends Node { |
| 416 | + public abstract Object execute(Node inliningTarget, Object value, boolean doArray); |
| 417 | + |
| 418 | + @Specialization(guards = {"lib.isBoolean(obj)"}) |
| 419 | + Object doBool(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 420 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 421 | + @Shared @Cached(inline = false) GilNode gil) { |
| 422 | + gil.release(true); |
| 423 | + try { |
| 424 | + return lib.asBoolean(obj); |
| 425 | + } catch (UnsupportedMessageException e) { |
| 426 | + throw CompilerDirectives.shouldNotReachHere(e); |
| 427 | + } finally { |
| 428 | + gil.acquire(); |
| 429 | + } |
416 | 430 | }
|
417 | 431 |
|
418 |
| - AddNode(boolean reverse) { |
419 |
| - super(BinaryArithmetic.Add.create(), reverse); |
| 432 | + @Specialization(guards = "lib.fitsInLong(obj)") |
| 433 | + Object doLong(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 434 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 435 | + @Shared @Cached(inline = false) GilNode gil) { |
| 436 | + assert !lib.isBoolean(obj); |
| 437 | + gil.release(true); |
| 438 | + try { |
| 439 | + return lib.asLong(obj); |
| 440 | + } catch (UnsupportedMessageException e) { |
| 441 | + throw CompilerDirectives.shouldNotReachHere(e); |
| 442 | + } finally { |
| 443 | + gil.acquire(); |
| 444 | + } |
420 | 445 | }
|
421 | 446 |
|
422 |
| - @Specialization(insertBefore = "doGeneric", guards = {"lib.hasArrayElements(left)", "lib.hasArrayElements(right)"}) |
423 |
| - static Object doForeignArray(Object left, Object right, |
424 |
| - @Cached PythonObjectFactory factory, |
425 |
| - @CachedLibrary(limit = "3") InteropLibrary lib, |
426 |
| - @Cached PForeignToPTypeNode convert, |
427 |
| - @Cached GilNode gil) { |
| 447 | + @Specialization(guards = {"!lib.fitsInLong(obj)", "lib.fitsInBigInteger(obj)"}) |
| 448 | + Object doBigInt(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 449 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 450 | + @Shared @Cached(inline = false) GilNode gil, |
| 451 | + @Shared @Cached(inline = false) PythonObjectFactory factory) { |
| 452 | + assert !lib.isBoolean(obj); |
428 | 453 | gil.release(true);
|
429 | 454 | try {
|
430 |
| - Object[] unpackedLeft = unpackForeignArray(left, lib, convert); |
431 |
| - Object[] unpackedRight = unpackForeignArray(right, lib, convert); |
432 |
| - if (unpackedLeft != null && unpackedRight != null) { |
433 |
| - Object[] result = Arrays.copyOf(unpackedLeft, unpackedLeft.length + unpackedRight.length); |
434 |
| - System.arraycopy(unpackedRight, 0, result, unpackedLeft.length, unpackedRight.length); |
435 |
| - return factory.createList(result); |
436 |
| - } |
| 455 | + return factory.createInt(lib.asBigInteger(obj)); |
| 456 | + } catch (UnsupportedMessageException e) { |
| 457 | + throw CompilerDirectives.shouldNotReachHere(e); |
437 | 458 | } finally {
|
438 | 459 | gil.acquire();
|
439 | 460 | }
|
440 |
| - return PNotImplemented.NOT_IMPLEMENTED; |
| 461 | + } |
| 462 | + |
| 463 | + @Specialization(guards = {"!lib.fitsInLong(obj)", "!lib.fitsInBigInteger(obj)", "lib.fitsInDouble(obj)"}) |
| 464 | + Object doDouble(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 465 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 466 | + @Shared @Cached(inline = false) GilNode gil) { |
| 467 | + assert !lib.isBoolean(obj); |
| 468 | + gil.release(true); |
| 469 | + try { |
| 470 | + return lib.asDouble(obj); |
| 471 | + } catch (UnsupportedMessageException e) { |
| 472 | + throw CompilerDirectives.shouldNotReachHere(e); |
| 473 | + } finally { |
| 474 | + gil.acquire(); |
| 475 | + } |
| 476 | + } |
| 477 | + |
| 478 | + @Specialization(guards = {"!lib.fitsInLong(obj)", "!lib.fitsInBigInteger(obj)", "!lib.fitsInDouble(obj)", "lib.isString(obj)"}) |
| 479 | + Object doString(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 480 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 481 | + @Cached(inline = false) TruffleString.SwitchEncodingNode switchEncodingNode, |
| 482 | + @Shared @Cached(inline = false) GilNode gil) { |
| 483 | + assert !lib.isBoolean(obj); |
| 484 | + gil.release(true); |
| 485 | + try { |
| 486 | + return switchEncodingNode.execute(lib.asTruffleString(obj), TS_ENCODING); |
| 487 | + } catch (UnsupportedMessageException e) { |
| 488 | + throw CompilerDirectives.shouldNotReachHere(e); |
| 489 | + } finally { |
| 490 | + gil.acquire(); |
| 491 | + } |
| 492 | + } |
| 493 | + |
| 494 | + @Specialization(guards = {"doArray", "!lib.isBoolean(obj)", "!lib.fitsInLong(obj)", "!lib.fitsInBigInteger(obj)", // |
| 495 | + "!lib.fitsInDouble(obj)", "!lib.isString(obj)", "lib.hasArrayElements(obj)"}) |
| 496 | + Object doArray(Object obj, @SuppressWarnings("unused") boolean doArray, |
| 497 | + @Shared @CachedLibrary(limit = "3") InteropLibrary lib, |
| 498 | + @Shared @Cached(inline = false) GilNode gil, |
| 499 | + @Cached(inline = false) PForeignToPTypeNode convert, |
| 500 | + @Shared @Cached(inline = false) PythonObjectFactory factory) { |
| 501 | + gil.release(true); |
| 502 | + try { |
| 503 | + return factory.createTuple(unpackForeignArray(obj, lib, convert)); |
| 504 | + } finally { |
| 505 | + gil.acquire(); |
| 506 | + } |
| 507 | + } |
| 508 | + |
| 509 | + @Fallback |
| 510 | + @SuppressWarnings("unused") |
| 511 | + public static Object doGeneric(Object left, boolean doArray) { |
| 512 | + return null; |
| 513 | + } |
| 514 | + } |
| 515 | + |
| 516 | + @Slot(value = SlotKind.nb_add, isComplex = true) |
| 517 | + @GenerateNodeFactory |
| 518 | + abstract static class AddNode extends BinaryOpBuiltinNode { |
| 519 | + @Specialization |
| 520 | + static Object doIt(VirtualFrame frame, Object left, Object right, |
| 521 | + @Bind("this") Node inliningTarget, |
| 522 | + @Cached IsForeignObjectNode isForeignLeft, |
| 523 | + @Cached IsForeignObjectNode isForeignRight, |
| 524 | + @Cached NormalizeForeignForBinopNode normalizeLeft, |
| 525 | + @Cached NormalizeForeignForBinopNode normalizeRight, |
| 526 | + @Cached PyNumberAddNode addNode) { |
| 527 | + boolean leftIsForeign = isForeignLeft.execute(inliningTarget, left); |
| 528 | + boolean rightIsForeign = isForeignRight.execute(inliningTarget, right); |
| 529 | + if (!leftIsForeign && !rightIsForeign) { |
| 530 | + return PNotImplemented.NOT_IMPLEMENTED; |
| 531 | + } |
| 532 | + |
| 533 | + Object newLeft = normalizeLeft.execute(inliningTarget, left, true); |
| 534 | + Object newRight = normalizeRight.execute(inliningTarget, right, true); |
| 535 | + assert newLeft == null || !IsForeignObjectNode.executeUncached(newLeft) : newLeft; |
| 536 | + assert newRight == null || !IsForeignObjectNode.executeUncached(newRight) : newRight; |
| 537 | + if (newLeft == null || newRight == null) { |
| 538 | + return PNotImplemented.NOT_IMPLEMENTED; |
| 539 | + } |
| 540 | + return addNode.execute(frame, inliningTarget, newLeft, newRight); |
441 | 541 | }
|
442 | 542 | }
|
443 | 543 |
|
|
0 commit comments