|
68 | 68 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.DirectUpcallNodeGen; |
69 | 69 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetNativeClassNodeFactory.GetNativeClassCachedNodeGen; |
70 | 70 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.GetTypeMemberNodeGen; |
71 | | -import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.IsPointerNodeFactory.IsPointerCachedNodeGen; |
| 71 | +import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.IsPointerNodeGen; |
72 | 72 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ObjectUpcallNodeGen; |
73 | 73 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.PointerCompareNodeGen; |
74 | 74 | import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToJavaNodeFactory.ToJavaCachedNodeGen; |
|
141 | 141 | import com.oracle.truffle.api.nodes.NodeUtil; |
142 | 142 | import com.oracle.truffle.api.profiles.BranchProfile; |
143 | 143 | import com.oracle.truffle.api.profiles.ConditionProfile; |
| 144 | +import com.oracle.truffle.api.profiles.ValueProfile; |
144 | 145 |
|
145 | 146 | public abstract class CExtNodes { |
146 | 147 |
|
@@ -543,13 +544,13 @@ public static Object doSlowPath(Object object, boolean forceNativeClass) { |
543 | 544 | return ((PythonNativeWrapper) object).getDelegate(); |
544 | 545 | } else if (IsBuiltinClassProfile.profileClassSlowPath(GetClassNode.getUncached().execute(object), PythonBuiltinClassType.TruffleObject)) { |
545 | 546 | if (forceNativeClass) { |
546 | | - return PythonLanguage.getCore().factory().createNativeClassWrapper((TruffleObject) object); |
| 547 | + return PythonObjectFactory.getUncached().createNativeClassWrapper((TruffleObject) object); |
547 | 548 | } |
548 | | - return PythonLanguage.getCore().factory().createNativeObjectWrapper((TruffleObject) object); |
| 549 | + return PythonObjectFactory.getUncached().createNativeObjectWrapper((TruffleObject) object); |
549 | 550 | } else if (object instanceof String || object instanceof Number || object instanceof Boolean || object instanceof PythonNativeNull || object instanceof PythonAbstractObject) { |
550 | 551 | return object; |
551 | 552 | } |
552 | | - throw PythonLanguage.getCore().raise(PythonErrorType.SystemError, "invalid object from native: %s", object); |
| 553 | + throw PRaiseNode.getUncached().raise(PythonErrorType.SystemError, "invalid object from native: %s", object); |
553 | 554 | } |
554 | 555 |
|
555 | 556 | // TODO(fa): Workaround for DSL bug: did not import factory at users |
@@ -1595,42 +1596,73 @@ protected ReadArgumentNode[] getArguments() { |
1595 | 1596 | } |
1596 | 1597 |
|
1597 | 1598 | // ----------------------------------------------------------------------------------------------------------------- |
| 1599 | + @GenerateUncached |
1598 | 1600 | public abstract static class IsPointerNode extends com.oracle.graal.python.nodes.PNodeWithContext { |
1599 | 1601 |
|
1600 | 1602 | public abstract boolean execute(PythonNativeWrapper obj); |
1601 | 1603 |
|
1602 | | - abstract static class IsPointerCachedNode extends IsPointerNode { |
| 1604 | + @Specialization(assumptions = {"singleContextAssumption()", "nativeObjectsAllManagedAssumption()"}) |
| 1605 | + boolean doFalse(@SuppressWarnings("unused") PythonNativeWrapper obj) { |
| 1606 | + return false; |
| 1607 | + } |
1603 | 1608 |
|
1604 | | - @Specialization(assumptions = {"singleContextAssumption()", "nativeObjectsAllManagedAssumption()"}) |
1605 | | - boolean doFalse(@SuppressWarnings("unused") PythonNativeWrapper obj) { |
1606 | | - return false; |
| 1609 | + @Specialization |
| 1610 | + boolean doGeneric(PythonNativeWrapper obj, |
| 1611 | + @Cached GetSpecialSingletonPtrNode getSpecialSingletonPtrNode, |
| 1612 | + @Cached("createClassProfile()") ValueProfile singletonProfile) { |
| 1613 | + if (obj.isNative()) { |
| 1614 | + return true; |
1607 | 1615 | } |
1608 | | - |
1609 | | - @Specialization |
1610 | | - boolean doGeneric(PythonNativeWrapper obj) { |
1611 | | - return obj.isNative(); |
1612 | | - } |
1613 | | - |
1614 | | - protected static Assumption nativeObjectsAllManagedAssumption() { |
1615 | | - return PythonLanguage.getContextRef().get().getNativeObjectsAllManagedAssumption(); |
| 1616 | + Object delegate = singletonProfile.profile(obj.getDelegate()); |
| 1617 | + if (isSpecialSingleton(delegate)) { |
| 1618 | + return getSpecialSingletonPtrNode.execute(delegate) != null; |
1616 | 1619 | } |
| 1620 | + return false; |
1617 | 1621 | } |
1618 | 1622 |
|
1619 | | - static final class IsPointerUncachedNode extends IsPointerNode { |
1620 | | - private static final IsPointerUncachedNode INSTANCE = new IsPointerUncachedNode(); |
| 1623 | + private static boolean isSpecialSingleton(Object delegate) { |
| 1624 | + return PythonLanguage.getSingletonNativePtrIdx(delegate) != -1; |
| 1625 | + } |
1621 | 1626 |
|
1622 | | - @Override |
1623 | | - public boolean execute(PythonNativeWrapper obj) { |
1624 | | - return obj.isNative(); |
1625 | | - } |
| 1627 | + protected static Assumption nativeObjectsAllManagedAssumption() { |
| 1628 | + return PythonLanguage.getContextRef().get().getNativeObjectsAllManagedAssumption(); |
1626 | 1629 | } |
1627 | 1630 |
|
1628 | 1631 | public static IsPointerNode create() { |
1629 | | - return IsPointerCachedNodeGen.create(); |
| 1632 | + return IsPointerNodeGen.create(); |
1630 | 1633 | } |
1631 | 1634 |
|
1632 | 1635 | public static IsPointerNode getUncached() { |
1633 | | - return IsPointerUncachedNode.INSTANCE; |
| 1636 | + return IsPointerNodeGen.getUncached(); |
| 1637 | + } |
| 1638 | + } |
| 1639 | + |
| 1640 | + // ----------------------------------------------------------------------------------------------------------------- |
| 1641 | + @GenerateUncached |
| 1642 | + public abstract static class GetSpecialSingletonPtrNode extends Node { |
| 1643 | + |
| 1644 | + public abstract Object execute(Object obj); |
| 1645 | + |
| 1646 | + @Specialization |
| 1647 | + Object doGeneric(Object obj, |
| 1648 | + @CachedContext(PythonLanguage.class) PythonContext context) { |
| 1649 | + if (obj instanceof PythonAbstractObject) { |
| 1650 | + return context.getSingletonNativePtr((PythonAbstractObject) obj); |
| 1651 | + } |
| 1652 | + return null; |
| 1653 | + } |
| 1654 | + } |
| 1655 | + |
| 1656 | + // ----------------------------------------------------------------------------------------------------------------- |
| 1657 | + @GenerateUncached |
| 1658 | + public abstract static class SetSpecialSingletonPtrNode extends Node { |
| 1659 | + |
| 1660 | + public abstract void execute(Object obj, Object ptr); |
| 1661 | + |
| 1662 | + @Specialization |
| 1663 | + void doGeneric(PythonAbstractObject obj, Object ptr, |
| 1664 | + @CachedContext(PythonLanguage.class) PythonContext context) { |
| 1665 | + context.setSingletonNativePtr(obj, ptr); |
1634 | 1666 | } |
1635 | 1667 | } |
1636 | 1668 |
|
@@ -1673,11 +1705,14 @@ public abstract static class GetTypeMemberNode extends CExtBaseNode { |
1673 | 1705 | * native context, so we can be sure that the "nativeClassStableAssumption" (which is |
1674 | 1706 | * per-context) is from the context in which this native object was created. |
1675 | 1707 | */ |
1676 | | - @Specialization(guards = {"cachedObj.equals(obj)", "memberName == cachedMemberName"}, limit = "1", assumptions = "getNativeClassStableAssumption(cachedObj)") |
1677 | | - public Object doCachedObj(@SuppressWarnings("unused") PythonNativeClass obj, @SuppressWarnings("unused") String memberName, |
| 1708 | + @Specialization(guards = {"isSameNativeObjectNode.execute(cachedObj, obj)", "memberName == cachedMemberName"}, // |
| 1709 | + limit = "1", // |
| 1710 | + assumptions = {"getNativeClassStableAssumption(cachedObj)", "singleContextAssumption()"}) |
| 1711 | + public Object doCachedObj(@SuppressWarnings("unused") PythonAbstractNativeObject obj, @SuppressWarnings("unused") String memberName, |
| 1712 | + @SuppressWarnings("unused") @Cached IsSameNativeObjectFastNode isSameNativeObjectNode, |
1678 | 1713 | @SuppressWarnings("unused") @Cached("memberName") String cachedMemberName, |
1679 | 1714 | @SuppressWarnings("unused") @Cached("getterFuncName(memberName)") String getterFuncName, |
1680 | | - @Cached("obj") @SuppressWarnings("unused") PythonNativeClass cachedObj, |
| 1715 | + @Cached("obj") @SuppressWarnings("unused") PythonAbstractNativeObject cachedObj, |
1681 | 1716 | @Cached("doSlowPath(obj, getterFuncName)") Object result) { |
1682 | 1717 | return result; |
1683 | 1718 | } |
@@ -1757,4 +1792,39 @@ static Object getNativeNullWithoutModule(@SuppressWarnings("unused") Object modu |
1757 | 1792 | } |
1758 | 1793 |
|
1759 | 1794 | } |
| 1795 | + |
| 1796 | + public abstract static class IsSameNativeObjectNode extends CExtBaseNode { |
| 1797 | + |
| 1798 | + public abstract boolean execute(PythonAbstractNativeObject left, PythonAbstractNativeObject right); |
| 1799 | + |
| 1800 | + protected static boolean doNativeFast(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { |
| 1801 | + // This check is a bit dangerous since we cannot be sure about the code that is running. |
| 1802 | + // Currently, we assume that the pointer object is a Sulong pointer and for this it's |
| 1803 | + // fine. |
| 1804 | + return left.equals(right); |
| 1805 | + } |
| 1806 | + |
| 1807 | + } |
| 1808 | + |
| 1809 | + @GenerateUncached |
| 1810 | + public abstract static class IsSameNativeObjectFastNode extends IsSameNativeObjectNode { |
| 1811 | + |
| 1812 | + @Specialization |
| 1813 | + boolean doSingleContext(PythonAbstractNativeObject left, PythonAbstractNativeObject right) { |
| 1814 | + return IsSameNativeObjectNode.doNativeFast(left, right); |
| 1815 | + } |
| 1816 | + } |
| 1817 | + |
| 1818 | + @GenerateUncached |
| 1819 | + public abstract static class IsSameNativeObjectSlowNode extends IsSameNativeObjectNode { |
| 1820 | + |
| 1821 | + @Specialization |
| 1822 | + boolean doSingleContext(PythonAbstractNativeObject left, PythonAbstractNativeObject right, |
| 1823 | + @Cached PointerCompareNode pointerCompareNode) { |
| 1824 | + if (IsSameNativeObjectNode.doNativeFast(left, right)) { |
| 1825 | + return true; |
| 1826 | + } |
| 1827 | + return pointerCompareNode.execute(SpecialMethodNames.__EQ__, left, right); |
| 1828 | + } |
| 1829 | + } |
1760 | 1830 | } |
0 commit comments