Skip to content

Commit 000e865

Browse files
committed
Implement HPyTracker
1 parent f26cd28 commit 000e865

File tree

3 files changed

+217
-15
lines changed

3 files changed

+217
-15
lines changed

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@
108108
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPySetAttr;
109109
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPySetItem;
110110
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTernaryArithmetic;
111+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTrackerAdd;
112+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTrackerCleanup;
113+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTrackerNew;
111114
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTupleFromArray;
112115
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTypeFromSpec;
113116
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContextFunctions.GraalHPyTypeGenericNew;
@@ -289,19 +292,19 @@ enum HPyContextMembers {
289292
CTX_LIST_BUILDER_NEW("ctx_ListBuilder_New"),
290293
CTX_LIST_BUILDER_SET("ctx_ListBuilder_Set"),
291294
CTX_LIST_BUILDER_BUILD("ctx_ListBuilder_Build"),
292-
CTX_LIST_BUILDER_CANCEL("ctx_ListBuilder_Cancel");
295+
CTX_LIST_BUILDER_CANCEL("ctx_ListBuilder_Cancel"),
296+
CTX_TRACKER_NEW("ctx_Tracker_New"),
297+
CTX_TRACKER_ADD("ctx_Tracker_Add"),
298+
CTX_TRACKER_REMOVE_ALL("ctx_Tracker_RemoveAll"),
299+
CTX_TRACKER_FREE("ctx_Tracker_Free");
293300

294301
private final String name;
295302

296303
HPyContextMembers(String name) {
297304
this.name = name;
298305
}
299306

300-
@CompilationFinal(dimensions = 1) private static final HPyContextMembers[] VALUES;
301-
static {
302-
HPyContextMembers[] members = values();
303-
VALUES = Arrays.copyOf(members, members.length);
304-
}
307+
@CompilationFinal(dimensions = 1) private static final HPyContextMembers[] VALUES = values();
305308

306309
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL_UNTIL_RETURN)
307310
public static HPyContextMembers getByName(String name) {
@@ -751,6 +754,11 @@ private static Object[] createMembers(PythonContext context) {
751754
members[HPyContextMembers.CTX_LIST_BUILDER_SET.ordinal()] = graalHPyBuilderSet;
752755
members[HPyContextMembers.CTX_LIST_BUILDER_BUILD.ordinal()] = new GraalHPyBuilderBuild(PList);
753756
members[HPyContextMembers.CTX_LIST_BUILDER_CANCEL.ordinal()] = graalHPyBuilderCancel;
757+
758+
members[HPyContextMembers.CTX_TRACKER_NEW.ordinal()] = new GraalHPyTrackerNew();
759+
members[HPyContextMembers.CTX_TRACKER_ADD.ordinal()] = new GraalHPyTrackerAdd();
760+
members[HPyContextMembers.CTX_TRACKER_REMOVE_ALL.ordinal()] = new GraalHPyTrackerCleanup(true);
761+
members[HPyContextMembers.CTX_TRACKER_FREE.ordinal()] = new GraalHPyTrackerCleanup(false);
754762
return members;
755763
}
756764

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

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
135135
import com.oracle.graal.python.runtime.sequence.PSequence;
136136
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
137+
import com.oracle.graal.python.util.OverflowException;
137138
import com.oracle.graal.python.util.PythonUtils;
138139
import com.oracle.truffle.api.CompilerAsserts;
139140
import com.oracle.truffle.api.CompilerDirectives;
@@ -1598,11 +1599,11 @@ Object execute(Object[] arguments,
15981599
}
15991600
}
16001601

1601-
@ExportLibrary(InteropLibrary.class)
1602-
public static final class GraalHPyBuilderNew extends GraalHPyContextFunction {
1602+
abstract static class GraalHPyBuilderNewBase extends GraalHPyContextFunction {
16031603

1604-
@ExportMessage
1605-
Object execute(Object[] arguments,
1604+
protected abstract Object createObject(int capacity);
1605+
1606+
protected final Object doExecute(Object[] arguments,
16061607
@Cached HPyAsContextNode asContextNode,
16071608
@Cached CastToJavaIntExactNode castToJavaIntExactNode,
16081609
@Cached HPyAsHandleNode asHandleNode) throws ArityException {
@@ -1614,11 +1615,7 @@ Object execute(Object[] arguments,
16141615
try {
16151616
int capacity = castToJavaIntExactNode.execute(arguments[1]);
16161617
if (capacity >= 0) {
1617-
Object[] data = new Object[capacity];
1618-
for (int i = 0; i < data.length; i++) {
1619-
data[i] = PNone.NONE;
1620-
}
1621-
return asHandleNode.execute(nativeContext, new ObjectSequenceStorage(data));
1618+
return asHandleNode.execute(nativeContext, createObject(capacity));
16221619
}
16231620
} catch (CannotCastException e) {
16241621
// fall through
@@ -1627,6 +1624,26 @@ Object execute(Object[] arguments,
16271624
}
16281625
}
16291626

1627+
@ExportLibrary(InteropLibrary.class)
1628+
public static final class GraalHPyBuilderNew extends GraalHPyBuilderNewBase {
1629+
@ExportMessage
1630+
Object execute(Object[] arguments,
1631+
@Cached HPyAsContextNode asContextNode,
1632+
@Cached CastToJavaIntExactNode castToJavaIntExactNode,
1633+
@Cached HPyAsHandleNode asHandleNode) throws ArityException {
1634+
return doExecute(arguments, asContextNode, castToJavaIntExactNode, asHandleNode);
1635+
}
1636+
1637+
@Override
1638+
protected Object createObject(int capacity) {
1639+
Object[] data = new Object[capacity];
1640+
for (int i = 0; i < data.length; i++) {
1641+
data[i] = PNone.NONE;
1642+
}
1643+
return new ObjectSequenceStorage(data);
1644+
}
1645+
}
1646+
16301647
@ExportLibrary(InteropLibrary.class)
16311648
public static final class GraalHPyBuilderSet extends GraalHPyContextFunction {
16321649

@@ -1759,4 +1776,94 @@ private static ObjectSequenceStorage cast(Object object) {
17591776

17601777
}
17611778

1779+
@ExportLibrary(InteropLibrary.class)
1780+
public static final class GraalHPyTrackerNew extends GraalHPyBuilderNewBase {
1781+
@ExportMessage
1782+
Object execute(Object[] arguments,
1783+
@Cached HPyAsContextNode asContextNode,
1784+
@Cached CastToJavaIntExactNode castToJavaIntExactNode,
1785+
@Cached HPyAsHandleNode asHandleNode) throws ArityException {
1786+
return doExecute(arguments, asContextNode, castToJavaIntExactNode, asHandleNode);
1787+
}
1788+
1789+
@Override
1790+
protected Object createObject(int capacity) {
1791+
return new GraalHPyTracker(capacity);
1792+
}
1793+
}
1794+
1795+
@ExportLibrary(InteropLibrary.class)
1796+
public static final class GraalHPyTrackerAdd extends GraalHPyContextFunction {
1797+
@ExportMessage
1798+
Object execute(Object[] arguments,
1799+
@Cached HPyAsContextNode asContextNode,
1800+
@Cached HPyAsPythonObjectNode asPythonObjectNode,
1801+
@Cached HPyEnsureHandleNode ensureHandleNode) throws ArityException, UnsupportedTypeException {
1802+
if (arguments.length != 3) {
1803+
CompilerDirectives.transferToInterpreterAndInvalidate();
1804+
throw ArityException.create(2, arguments.length);
1805+
}
1806+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1807+
GraalHPyTracker builder = cast(asPythonObjectNode.execute(nativeContext, arguments[1]));
1808+
if (builder == null) {
1809+
// that's really unexpected since the C signature should enforce a valid builder but
1810+
// someone could have messed it up
1811+
CompilerDirectives.transferToInterpreterAndInvalidate();
1812+
throw UnsupportedTypeException.create(arguments, "invalid builder object");
1813+
}
1814+
try {
1815+
builder.add(ensureHandleNode.execute(nativeContext, arguments[2]));
1816+
} catch (OverflowException | OutOfMemoryError e) {
1817+
return -1;
1818+
}
1819+
return 0;
1820+
}
1821+
1822+
private static GraalHPyTracker cast(Object object) {
1823+
if (object instanceof GraalHPyTracker) {
1824+
return (GraalHPyTracker) object;
1825+
}
1826+
return null;
1827+
}
1828+
}
1829+
1830+
@ExportLibrary(InteropLibrary.class)
1831+
public static final class GraalHPyTrackerCleanup extends GraalHPyContextFunction {
1832+
private final boolean removeAll;
1833+
1834+
public GraalHPyTrackerCleanup(boolean removeAll) {
1835+
this.removeAll = removeAll;
1836+
}
1837+
1838+
@ExportMessage
1839+
Object execute(Object[] arguments,
1840+
@Cached HPyAsContextNode asContextNode,
1841+
@Cached HPyAsPythonObjectNode asPythonObjectNode) throws ArityException, UnsupportedTypeException {
1842+
if (arguments.length != 2) {
1843+
CompilerDirectives.transferToInterpreterAndInvalidate();
1844+
throw ArityException.create(2, arguments.length);
1845+
}
1846+
GraalHPyContext nativeContext = asContextNode.execute(arguments[0]);
1847+
GraalHPyTracker builder = cast(asPythonObjectNode.execute(nativeContext, arguments[1]));
1848+
if (builder == null) {
1849+
// that's really unexpected since the C signature should enforce a valid builder but
1850+
// someone could have messed it up
1851+
CompilerDirectives.transferToInterpreterAndInvalidate();
1852+
throw UnsupportedTypeException.create(arguments, "invalid builder object");
1853+
}
1854+
if (removeAll) {
1855+
builder.removeAll();
1856+
} else {
1857+
builder.free(nativeContext, ConditionProfile.getUncached());
1858+
}
1859+
return 0;
1860+
}
1861+
1862+
private static GraalHPyTracker cast(Object object) {
1863+
if (object instanceof GraalHPyTracker) {
1864+
return (GraalHPyTracker) object;
1865+
}
1866+
return null;
1867+
}
1868+
}
17621869
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.cext.hpy;
42+
43+
import java.util.Arrays;
44+
45+
import com.oracle.graal.python.util.OverflowException;
46+
import com.oracle.graal.python.util.PythonUtils;
47+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
48+
import com.oracle.truffle.api.profiles.ConditionProfile;
49+
50+
public final class GraalHPyTracker {
51+
private static final int HPYTRACKER_INITIAL_SIZE = 5;
52+
53+
private GraalHPyHandle[] handles;
54+
private int cursor;
55+
56+
public GraalHPyTracker(int capacity) {
57+
int size = capacity == 0 ? HPYTRACKER_INITIAL_SIZE : capacity;
58+
this.handles = new GraalHPyHandle[size];
59+
}
60+
61+
public void add(GraalHPyHandle h) throws OverflowException {
62+
handles[cursor++] = h;
63+
if (handles.length <= cursor) {
64+
resize();
65+
}
66+
}
67+
68+
@TruffleBoundary
69+
private void resize() throws OverflowException {
70+
handles = Arrays.copyOf(handles, PythonUtils.multiplyExact(handles.length, 2) - 1);
71+
}
72+
73+
public void free(GraalHPyContext nativeContext, ConditionProfile profile) {
74+
assert cursor <= handles.length;
75+
for (int i = 0; i < cursor; i++) {
76+
handles[i].close(nativeContext, profile);
77+
}
78+
cursor = 0;
79+
}
80+
81+
public void removeAll() {
82+
for (int i = 0; i < handles.length; i++) {
83+
handles[i] = null;
84+
}
85+
cursor = 0;
86+
}
87+
}

0 commit comments

Comments
 (0)