Skip to content

Commit 784b1ea

Browse files
committed
Implement context functions for tuple/list builder
1 parent 4326c20 commit 784b1ea

File tree

3 files changed

+204
-11
lines changed

3 files changed

+204
-11
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyContext.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyArithmetic;
6767
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyAsIndex;
6868
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyAsPyObject;
69+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBuilderBuild;
70+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBuilderCancel;
71+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBuilderNew;
72+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBuilderSet;
6973
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBytesAsString;
7074
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyBytesGetSize;
7175
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyCallBuiltinFunction;
@@ -251,7 +255,15 @@ enum HPyContextMembers {
251255
CTX_HASH("ctx_Hash"),
252256
CTX_NUMBER_CHECK("ctx_Number_Check"),
253257
CTX_LENGTH("ctx_Length"),
254-
CTX_TUPLE_FROMARRAY("ctx_Tuple_FromArray");
258+
CTX_TUPLE_FROMARRAY("ctx_Tuple_FromArray"),
259+
CTX_TUPLE_BUILDER_NEW("ctx_TupleBuilder_New"),
260+
CTX_TUPLE_BUILDER_SET("ctx_TupleBuilder_Set"),
261+
CTX_TUPLE_BUILDER_BUILD("ctx_TupleBuilder_Build"),
262+
CTX_TUPLE_BUILDER_CANCEL("ctx_TupleBuilder_Cancel"),
263+
CTX_LIST_BUILDER_NEW("ctx_ListBuilder_New"),
264+
CTX_LIST_BUILDER_SET("ctx_ListBuilder_Set"),
265+
CTX_LIST_BUILDER_BUILD("ctx_ListBuilder_Build"),
266+
CTX_LIST_BUILDER_CANCEL("ctx_ListBuilder_Cancel");
255267

256268
private final String name;
257269

@@ -542,6 +554,19 @@ private static Object[] createMembers(PythonContext context) {
542554
members[HPyContextMembers.CTX_NUMBER_CHECK.ordinal()] = new GraalHPyIsNumber();
543555
members[HPyContextMembers.CTX_LENGTH.ordinal()] = new GraalHPyCallBuiltinFunction(BuiltinNames.LEN, 1, GraalHPyConversionNodeSupplier.TO_INT64);
544556
members[HPyContextMembers.CTX_TUPLE_FROMARRAY.ordinal()] = new GraalHPyTupleFromArray();
557+
558+
GraalHPyBuilderNew graalHPyBuilderNew = new GraalHPyBuilderNew();
559+
GraalHPyBuilderSet graalHPyBuilderSet = new GraalHPyBuilderSet();
560+
GraalHPyBuilderCancel graalHPyBuilderCancel = new GraalHPyBuilderCancel();
561+
members[HPyContextMembers.CTX_TUPLE_BUILDER_NEW.ordinal()] = graalHPyBuilderNew;
562+
members[HPyContextMembers.CTX_TUPLE_BUILDER_SET.ordinal()] = graalHPyBuilderSet;
563+
members[HPyContextMembers.CTX_TUPLE_BUILDER_BUILD.ordinal()] = new GraalHPyBuilderBuild(PTuple);
564+
members[HPyContextMembers.CTX_TUPLE_BUILDER_CANCEL.ordinal()] = graalHPyBuilderCancel;
565+
566+
members[HPyContextMembers.CTX_LIST_BUILDER_NEW.ordinal()] = graalHPyBuilderNew;
567+
members[HPyContextMembers.CTX_LIST_BUILDER_SET.ordinal()] = graalHPyBuilderSet;
568+
members[HPyContextMembers.CTX_LIST_BUILDER_BUILD.ordinal()] = new GraalHPyBuilderBuild(PList);
569+
members[HPyContextMembers.CTX_LIST_BUILDER_CANCEL.ordinal()] = graalHPyBuilderCancel;
545570
return members;
546571
}
547572

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyContextFunctions.java

Lines changed: 166 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
import java.nio.charset.StandardCharsets;
6262
import java.util.WeakHashMap;
6363

64-
import com.oracle.truffle.api.interop.UnknownIdentifierException;
6564
import org.graalvm.collections.Pair;
6665

6766
import com.oracle.graal.python.PythonLanguage;
@@ -98,6 +97,8 @@
9897
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
9998
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
10099
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
100+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
101+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.NoGeneralizationNode;
101102
import com.oracle.graal.python.builtins.objects.dict.PDict;
102103
import com.oracle.graal.python.builtins.objects.function.PArguments;
103104
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
@@ -140,6 +141,7 @@
140141
import com.oracle.graal.python.runtime.exception.PException;
141142
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
142143
import com.oracle.graal.python.runtime.sequence.PSequence;
144+
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
143145
import com.oracle.graal.python.util.PythonUtils;
144146
import com.oracle.truffle.api.CompilerAsserts;
145147
import com.oracle.truffle.api.CompilerDirectives;
@@ -156,6 +158,7 @@
156158
import com.oracle.truffle.api.interop.InteropLibrary;
157159
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
158160
import com.oracle.truffle.api.interop.TruffleObject;
161+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
159162
import com.oracle.truffle.api.interop.UnsupportedMessageException;
160163
import com.oracle.truffle.api.interop.UnsupportedTypeException;
161164
import com.oracle.truffle.api.library.CachedLibrary;
@@ -230,15 +233,7 @@ Object execute(Object[] arguments,
230233
}
231234
GraalHPyContext hpyContext = asContextNode.execute(arguments[0]);
232235
GraalHPyHandle handle = ensureHandleNode.execute(hpyContext, arguments[1]);
233-
if (handle.isNative()) {
234-
try {
235-
hpyContext.releaseHPyHandleForObject((int) handle.asPointer());
236-
} catch (UnsupportedMessageException e) {
237-
CompilerDirectives.transferToInterpreterAndInvalidate();
238-
throw new IllegalStateException("trying to release non-native handle that claims to be native");
239-
}
240-
}
241-
// nothing to do if the handle never got 'toNative'
236+
handle.close(hpyContext);
242237
return 0;
243238
}
244239
}
@@ -1675,4 +1670,165 @@ Object execute(Object[] arguments,
16751670
}
16761671
}
16771672
}
1673+
1674+
@ExportLibrary(InteropLibrary.class)
1675+
public static final class GraalHPyBuilderNew extends GraalHPyContextFunction {
1676+
1677+
@ExportMessage
1678+
Object execute(Object[] arguments,
1679+
@Cached HPyAsContextNode asContextNode,
1680+
@Cached CastToJavaIntExactNode castToJavaIntExactNode,
1681+
@Cached HPyAsHandleNode asHandleNode) throws ArityException {
1682+
if (arguments.length != 2) {
1683+
CompilerDirectives.transferToInterpreterAndInvalidate();
1684+
throw ArityException.create(2, arguments.length);
1685+
}
1686+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1687+
try {
1688+
int capacity = castToJavaIntExactNode.execute(arguments[1]);
1689+
if (capacity >= 0) {
1690+
Object[] data = new Object[capacity];
1691+
for (int i = 0; i < data.length; i++) {
1692+
data[i] = PNone.NONE;
1693+
}
1694+
return asHandleNode.execute(nativeContext, new ObjectSequenceStorage(data));
1695+
}
1696+
} catch (CannotCastException e) {
1697+
// fall through
1698+
}
1699+
return nativeContext.getNullHandle();
1700+
}
1701+
}
1702+
1703+
@ExportLibrary(InteropLibrary.class)
1704+
public static final class GraalHPyBuilderSet extends GraalHPyContextFunction {
1705+
1706+
@ExportMessage
1707+
Object execute(Object[] arguments,
1708+
@Cached HPyAsContextNode asContextNode,
1709+
@Cached HPyAsPythonObjectNode asPythonObjectNode,
1710+
@Cached CastToJavaIntExactNode castToJavaIntExactNode,
1711+
@Cached SequenceStorageNodes.SetItemDynamicNode setItemNode,
1712+
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode) throws ArityException, UnsupportedTypeException {
1713+
if (arguments.length != 4) {
1714+
CompilerDirectives.transferToInterpreterAndInvalidate();
1715+
throw ArityException.create(4, arguments.length);
1716+
}
1717+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1718+
Object builder = asPythonObjectNode.execute(nativeContext, arguments[1]);
1719+
if (!isValid(builder)) {
1720+
// that's really unexpected since the C signature should enforce a valid builder but
1721+
// someone could have messed it up
1722+
CompilerDirectives.transferToInterpreterAndInvalidate();
1723+
throw UnsupportedTypeException.create(arguments, "invalid builder object");
1724+
}
1725+
ObjectSequenceStorage storage = (ObjectSequenceStorage) builder;
1726+
1727+
try {
1728+
int idx = castToJavaIntExactNode.execute(arguments[2]);
1729+
Object value = asPythonObjectNode.execute(nativeContext, arguments[3]);
1730+
setItemNode.execute(NoGeneralizationNode.DEFAULT, storage, idx, value);
1731+
} catch (CannotCastException e) {
1732+
// fall through
1733+
} catch (PException e) {
1734+
transformExceptionToNativeNode.execute(e);
1735+
}
1736+
return 0;
1737+
}
1738+
1739+
private boolean isValid(Object object) {
1740+
return object instanceof ObjectSequenceStorage;
1741+
}
1742+
1743+
}
1744+
1745+
@ExportLibrary(InteropLibrary.class)
1746+
public static final class GraalHPyBuilderBuild extends GraalHPyContextFunction {
1747+
1748+
private final PythonBuiltinClassType type;
1749+
1750+
public GraalHPyBuilderBuild(PythonBuiltinClassType type) {
1751+
assert type == PythonBuiltinClassType.PTuple || type == PythonBuiltinClassType.PList;
1752+
this.type = type;
1753+
}
1754+
1755+
@ExportMessage
1756+
Object execute(Object[] arguments,
1757+
@Cached HPyAsContextNode asContextNode,
1758+
@Cached HPyAsPythonObjectNode asPythonObjectNode,
1759+
@Cached PythonObjectFactory factory,
1760+
@Cached HPyAsHandleNode asHandleNode) throws ArityException, UnsupportedTypeException {
1761+
if (arguments.length != 2) {
1762+
CompilerDirectives.transferToInterpreterAndInvalidate();
1763+
throw ArityException.create(2, arguments.length);
1764+
}
1765+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1766+
ObjectSequenceStorage builder = cast(asPythonObjectNode.execute(nativeContext, arguments[1]));
1767+
if (builder == null) {
1768+
// that's really unexpected since the C signature should enforce a valid builder but
1769+
// someone could have messed it up
1770+
CompilerDirectives.transferToInterpreterAndInvalidate();
1771+
throw UnsupportedTypeException.create(arguments, "invalid builder object");
1772+
}
1773+
1774+
Object sequence;
1775+
switch (type) {
1776+
case PTuple:
1777+
sequence = factory.createTuple(builder);
1778+
break;
1779+
case PList:
1780+
sequence = factory.createList(builder);
1781+
break;
1782+
default:
1783+
throw CompilerDirectives.shouldNotReachHere();
1784+
}
1785+
return asHandleNode.execute(sequence);
1786+
}
1787+
1788+
private static ObjectSequenceStorage cast(Object object) {
1789+
if (object instanceof ObjectSequenceStorage) {
1790+
return (ObjectSequenceStorage) object;
1791+
}
1792+
return null;
1793+
}
1794+
1795+
}
1796+
1797+
@ExportLibrary(InteropLibrary.class)
1798+
public static final class GraalHPyBuilderCancel extends GraalHPyContextFunction {
1799+
1800+
@ExportMessage
1801+
Object execute(Object[] arguments,
1802+
@Cached HPyAsContextNode asContextNode,
1803+
@Cached HPyEnsureHandleNode ensureHandleNode,
1804+
@Cached HPyAsPythonObjectNode asPythonObjectNode) throws ArityException, UnsupportedTypeException {
1805+
if (arguments.length != 2) {
1806+
CompilerDirectives.transferToInterpreterAndInvalidate();
1807+
throw ArityException.create(2, arguments.length);
1808+
}
1809+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1810+
GraalHPyHandle hpyHandle = ensureHandleNode.execute(nativeContext, arguments[1]);
1811+
hpyHandle.close(nativeContext);
1812+
1813+
// be pedantic and also check what we are cancelling
1814+
ObjectSequenceStorage builder = cast(asPythonObjectNode.execute(nativeContext, hpyHandle));
1815+
if (builder == null) {
1816+
// that's really unexpected since the C signature should enforce a valid builder but
1817+
// someone could have messed it up
1818+
CompilerDirectives.transferToInterpreterAndInvalidate();
1819+
throw UnsupportedTypeException.create(arguments, "invalid builder object");
1820+
}
1821+
1822+
return 0;
1823+
}
1824+
1825+
private static ObjectSequenceStorage cast(Object object) {
1826+
if (object instanceof ObjectSequenceStorage) {
1827+
return (ObjectSequenceStorage) object;
1828+
}
1829+
return null;
1830+
}
1831+
1832+
}
1833+
16781834
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyHandle.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,16 @@ Object readMember(String key) throws UnknownIdentifierException {
175175
public GraalHPyHandle copy() {
176176
return new GraalHPyHandle(delegate);
177177
}
178+
179+
public void close(GraalHPyContext hpyContext) {
180+
if (isPointer()) {
181+
try {
182+
hpyContext.releaseHPyHandleForObject((int) asPointer());
183+
} catch (UnsupportedMessageException e) {
184+
CompilerDirectives.transferToInterpreterAndInvalidate();
185+
throw new IllegalStateException("trying to release non-native handle that claims to be native");
186+
}
187+
}
188+
// nothing to do if the handle never got 'toNative'
189+
}
178190
}

0 commit comments

Comments
 (0)