|
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