|
187 | 187 | import com.oracle.graal.python.builtins.objects.ints.PInt;
|
188 | 188 | import com.oracle.graal.python.builtins.objects.list.PList;
|
189 | 189 | import com.oracle.graal.python.builtins.objects.object.PythonObject;
|
| 190 | +import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass; |
190 | 191 | import com.oracle.graal.python.builtins.objects.type.PythonClass;
|
191 | 192 | import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
|
192 | 193 | import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
|
193 | 194 | import com.oracle.graal.python.lib.CanBeDoubleNodeGen;
|
194 | 195 | import com.oracle.graal.python.lib.PyFloatAsDoubleNodeGen;
|
195 | 196 | import com.oracle.graal.python.lib.PyIndexCheckNodeGen;
|
| 197 | +import com.oracle.graal.python.lib.PyLongAsDoubleNodeGen; |
196 | 198 | import com.oracle.graal.python.lib.PyObjectSizeNodeGen;
|
197 | 199 | import com.oracle.graal.python.nodes.BuiltinNames;
|
198 | 200 | import com.oracle.graal.python.nodes.ErrorMessages;
|
|
203 | 205 | import com.oracle.graal.python.nodes.call.CallTargetInvokeNode;
|
204 | 206 | import com.oracle.graal.python.nodes.call.GenericInvokeNode;
|
205 | 207 | import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
|
| 208 | +import com.oracle.graal.python.nodes.classes.IsSubtypeNode; |
206 | 209 | import com.oracle.graal.python.nodes.classes.IsSubtypeNodeGen;
|
207 | 210 | import com.oracle.graal.python.nodes.expression.BinaryArithmetic;
|
208 | 211 | import com.oracle.graal.python.nodes.expression.InplaceArithmetic;
|
@@ -551,10 +554,10 @@ enum HPyContextMember {
|
551 | 554 | CTX_LONG_ASSIZE_T("ctx_Long_AsSize_t"),
|
552 | 555 | CTX_LONG_ASSSIZE_T("ctx_Long_AsSsize_t"),
|
553 | 556 | CTX_LONG_ASVOIDPTR("ctx_Long_AsVoidPtr"),
|
554 |
| - CTX_LONG_ASDOUBLE("ctx_Long_AsDouble"), |
| 557 | + CTX_LONG_ASDOUBLE("ctx_Long_AsDouble", signature(Double, HPy)), |
555 | 558 | CTX_NEW("ctx_New", signature(HPy, HPy, DataPtrPtr)),
|
556 | 559 | CTX_TYPE("ctx_Type"),
|
557 |
| - CTX_TYPECHECK("ctx_TypeCheck"), |
| 560 | + CTX_TYPECHECK("ctx_TypeCheck", signature(Long, HPy, HPy)), |
558 | 561 | CTX_IS("ctx_Is"),
|
559 | 562 | CTX_TYPE_GENERIC_NEW("ctx_Type_GenericNew", signature(HPy, HPy)),
|
560 | 563 | CTX_FLOAT_FROMDOUBLE("ctx_Float_FromDouble", signature(HPy, Double)),
|
@@ -788,7 +791,11 @@ public static GraalHPyNativeSymbol getGetterFunctionName(LLVMType llvmType) {
|
788 | 791 | }
|
789 | 792 | }
|
790 | 793 |
|
| 794 | + private static final int IMMUTABLE_HANDLE_COUNT = 256; |
| 795 | + |
791 | 796 | private GraalHPyHandle[] hpyHandleTable = new GraalHPyHandle[]{GraalHPyHandle.NULL_HANDLE};
|
| 797 | + private int nextHandle = 1; |
| 798 | + |
792 | 799 | private GraalHPyHandle[] hpyGlobalsTable = new GraalHPyHandle[]{GraalHPyHandle.NULL_HANDLE};
|
793 | 800 | private final HandleStack freeStack = new HandleStack(16);
|
794 | 801 | Object nativePointer;
|
@@ -831,6 +838,16 @@ public GraalHPyContext(PythonContext context, Object hpyLibrary) {
|
831 | 838 | super(context, hpyLibrary, GraalHPyConversionNodeSupplier.HANDLE);
|
832 | 839 | this.slowPathFactory = context.factory();
|
833 | 840 | this.hpyContextMembers = createMembers(context, getName());
|
| 841 | + for (Object member : hpyContextMembers) { |
| 842 | + if (member instanceof GraalHPyHandle) { |
| 843 | + GraalHPyHandle handle = (GraalHPyHandle) member; |
| 844 | + int id = handle.getId(this, ConditionProfile.getUncached()); |
| 845 | + assert id > 0 && id < IMMUTABLE_HANDLE_COUNT; |
| 846 | + |
| 847 | + } |
| 848 | + } |
| 849 | + hpyHandleTable = Arrays.copyOf(hpyHandleTable, IMMUTABLE_HANDLE_COUNT * 2); |
| 850 | + nextHandle = IMMUTABLE_HANDLE_COUNT; |
834 | 851 | this.useNativeFastPaths = context.getLanguage().getEngineOption(PythonOptions.HPyEnableJNIFastPaths);
|
835 | 852 | }
|
836 | 853 |
|
@@ -1340,9 +1357,11 @@ public enum Counter {
|
1340 | 1357 | UpcallSetItemI,
|
1341 | 1358 | UpcallDup,
|
1342 | 1359 | UpcallNumberCheck,
|
| 1360 | + UpcallTypeCheck, |
1343 | 1361 | UpcallLength,
|
1344 | 1362 | UpcallListCheck,
|
1345 | 1363 | UpcallLongAsLong,
|
| 1364 | + UpcallLongAsDouble, |
1346 | 1365 | UpcallLongFromLong,
|
1347 | 1366 | UpcallFloatAsDouble,
|
1348 | 1367 | UpcallFloatFromDouble,
|
@@ -1418,6 +1437,22 @@ public final long ctxLongAsLong(long handle) {
|
1418 | 1437 | }
|
1419 | 1438 | }
|
1420 | 1439 |
|
| 1440 | + public final double ctxLongAsDouble(long handle) { |
| 1441 | + Counter.UpcallLongAsDouble.increment(); |
| 1442 | + |
| 1443 | + if (GraalHPyBoxing.isBoxedInt(handle)) { |
| 1444 | + return GraalHPyBoxing.unboxInt(handle); |
| 1445 | + } else { |
| 1446 | + Object object = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate(); |
| 1447 | + try { |
| 1448 | + return (double) PyLongAsDoubleNodeGen.getUncached().execute(object); |
| 1449 | + } catch (PException e) { |
| 1450 | + HPyTransformExceptionToNativeNodeGen.getUncached().execute(this, e); |
| 1451 | + return -1L; |
| 1452 | + } |
| 1453 | + } |
| 1454 | + } |
| 1455 | + |
1421 | 1456 | public final long ctxLongFromLong(long l) {
|
1422 | 1457 | Counter.UpcallLongFromLong.increment();
|
1423 | 1458 |
|
@@ -1684,6 +1719,59 @@ public final int ctxNumberCheck(long handle) {
|
1684 | 1719 | }
|
1685 | 1720 | }
|
1686 | 1721 |
|
| 1722 | + private static PythonBuiltinClassType getBuiltinClass(Object cls) { |
| 1723 | + if (cls instanceof PythonBuiltinClassType) { |
| 1724 | + return (PythonBuiltinClassType) cls; |
| 1725 | + } else if (cls instanceof PythonBuiltinClass) { |
| 1726 | + return ((PythonBuiltinClass) cls).getType(); |
| 1727 | + } else { |
| 1728 | + return null; |
| 1729 | + } |
| 1730 | + } |
| 1731 | + |
| 1732 | + public final int ctxTypeCheck(long handle, long typeHandle) { |
| 1733 | + Counter.UpcallTypeCheck.increment(); |
| 1734 | + Object receiver; |
| 1735 | + if (GraalHPyBoxing.isBoxedDouble(handle)) { |
| 1736 | + receiver = PythonBuiltinClassType.PFloat; |
| 1737 | + } else if (GraalHPyBoxing.isBoxedInt(handle)) { |
| 1738 | + receiver = PythonBuiltinClassType.PInt; |
| 1739 | + } else { |
| 1740 | + receiver = GetClassNode.getUncached().execute(getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate()); |
| 1741 | + } |
| 1742 | + Object type = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(typeHandle)).getDelegate(); |
| 1743 | + |
| 1744 | + if (receiver == type) { |
| 1745 | + return 1; |
| 1746 | + } |
| 1747 | + |
| 1748 | + PythonBuiltinClassType receiverBuiltin = getBuiltinClass(receiver); |
| 1749 | + if (receiverBuiltin != null) { |
| 1750 | + PythonBuiltinClassType typeBuiltin = getBuiltinClass(type); |
| 1751 | + if (typeBuiltin == null) { |
| 1752 | + // builtin type cannot be a subclass of a non-builtin type |
| 1753 | + return 0; |
| 1754 | + } |
| 1755 | + // fast path for builtin types: walk class hierarchy |
| 1756 | + while (true) { |
| 1757 | + if (receiverBuiltin == typeBuiltin) { |
| 1758 | + return 1; |
| 1759 | + } |
| 1760 | + if (receiverBuiltin == PythonBuiltinClassType.PythonObject) { |
| 1761 | + return 0; |
| 1762 | + } |
| 1763 | + receiverBuiltin = receiverBuiltin.getBase(); |
| 1764 | + } |
| 1765 | + } |
| 1766 | + |
| 1767 | + try { |
| 1768 | + return IsSubtypeNode.getUncached().execute(receiver, type) ? 1 : 0; |
| 1769 | + } catch (PException e) { |
| 1770 | + HPyTransformExceptionToNativeNodeGen.getUncached().execute(this, e); |
| 1771 | + return 0; |
| 1772 | + } |
| 1773 | + } |
| 1774 | + |
1687 | 1775 | public final long ctxLength(long handle) {
|
1688 | 1776 | Counter.UpcallLength.increment();
|
1689 | 1777 | assert GraalHPyBoxing.isBoxedHandle(handle);
|
@@ -2244,36 +2332,34 @@ private synchronized int allocateHPyGlobal() {
|
2244 | 2332 |
|
2245 | 2333 | private long nativeSpacePointers;
|
2246 | 2334 |
|
2247 |
| - @TruffleBoundary(allowInlining = true) |
2248 |
| - private int allocateHandle() { |
2249 |
| - int freeItem = freeStack.pop(); |
2250 |
| - if (freeItem != -1) { |
2251 |
| - assert 0 <= freeItem && freeItem < hpyHandleTable.length; |
2252 |
| - assert hpyHandleTable[freeItem] == null; |
2253 |
| - return freeItem; |
2254 |
| - } |
2255 |
| - for (int i = 1; i < hpyHandleTable.length; i++) { |
2256 |
| - if (hpyHandleTable[i] == null) { |
2257 |
| - return i; |
2258 |
| - } |
| 2335 | + private int resizeHandleTable() { |
| 2336 | + CompilerAsserts.neverPartOfCompilation(); |
| 2337 | + assert nextHandle == hpyHandleTable.length; |
| 2338 | + int newSize = Math.max(16, hpyHandleTable.length * 2); |
| 2339 | + LOGGER.fine(() -> "resizing HPy handle table to " + newSize); |
| 2340 | + hpyHandleTable = Arrays.copyOf(hpyHandleTable, newSize); |
| 2341 | + if (useNativeFastPaths && isPointer()) { |
| 2342 | + reallocateNativeSpacePointersMirror(); |
2259 | 2343 | }
|
2260 |
| - return -1; |
| 2344 | + return nextHandle++; |
2261 | 2345 | }
|
2262 | 2346 |
|
2263 |
| - public final synchronized int getHPyHandleForObject(GraalHPyHandle object) { |
| 2347 | + public final int getHPyHandleForObject(GraalHPyHandle object) { |
2264 | 2348 | // find free association
|
2265 |
| - int handle = allocateHandle(); |
| 2349 | + |
| 2350 | + int handle = freeStack.pop(); |
2266 | 2351 | if (handle == -1) {
|
2267 |
| - // resize |
2268 |
| - int newSize = Math.max(16, hpyHandleTable.length * 2); |
2269 |
| - LOGGER.fine(() -> "resizing HPy handle table to " + newSize); |
2270 |
| - hpyHandleTable = Arrays.copyOf(hpyHandleTable, newSize); |
2271 |
| - if (useNativeFastPaths && isPointer()) { |
2272 |
| - reallocateNativeSpacePointersMirror(); |
| 2352 | + if (nextHandle < hpyHandleTable.length) { |
| 2353 | + handle = nextHandle++; |
| 2354 | + } else { |
| 2355 | + CompilerDirectives.transferToInterpreter(); |
| 2356 | + handle = resizeHandleTable(); |
2273 | 2357 | }
|
2274 |
| - handle = allocateHandle(); |
2275 | 2358 | }
|
2276 |
| - assert handle > 0; |
| 2359 | + |
| 2360 | + assert 0 <= handle && handle < hpyHandleTable.length; |
| 2361 | + assert hpyHandleTable[handle] == null; |
| 2362 | + |
2277 | 2363 | hpyHandleTable[handle] = object;
|
2278 | 2364 | if (useNativeFastPaths && isPointer()) {
|
2279 | 2365 | mirrorNativeSpacePointerToNative(object, handle);
|
@@ -2362,6 +2448,9 @@ synchronized boolean releaseHPyHandleForObject(int handle) {
|
2362 | 2448 | if (LOGGER.isLoggable(Level.FINER)) {
|
2363 | 2449 | LOGGER.finer(() -> "releasing HPy handle " + handle);
|
2364 | 2450 | }
|
| 2451 | + if (handle < IMMUTABLE_HANDLE_COUNT) { |
| 2452 | + return false; |
| 2453 | + } |
2365 | 2454 | hpyHandleTable[handle] = null;
|
2366 | 2455 | freeStack.push(handle);
|
2367 | 2456 | return true;
|
|
0 commit comments