Skip to content

Commit 549661d

Browse files
committed
Implement cache for resolving handles.
1 parent 2cdeedf commit 549661d

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ uint64_t (*PY_TRUFFLE_CEXT_LANDING_L)(void* name, ...);
5353
double (*PY_TRUFFLE_CEXT_LANDING_D)(void* name, ...);
5454
void* (*PY_TRUFFLE_CEXT_LANDING_PTR)(void* name, ...);
5555

56+
static void* cache;
57+
void* (*resolve_handle)(void* cache, uint64_t handle);
58+
5659
__attribute__((constructor (__COUNTER__)))
5760
static void initialize_upcall_functions() {
5861
PY_TRUFFLE_CEXT = (void*)polyglot_import("python_cext");
@@ -70,6 +73,12 @@ static void initialize_upcall_functions() {
7073
Py_NoValue = UPCALL_CEXT_O(polyglot_from_string("Py_NoValue", SRC_CS));
7174
}
7275

76+
__attribute__((constructor (__COUNTER__)))
77+
static void initialize_handle_cache() {
78+
cache = polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_HandleCache_Create", truffle_managed_from_handle);
79+
resolve_handle = ((void* (*)(void* cache, uint64_t handle))polyglot_get_member(PY_TRUFFLE_CEXT, polyglot_from_string("PyTruffle_HandleCache_GetOrInsert", SRC_CS)));
80+
}
81+
7382
static void initialize_type_structure(PyTypeObject* structure, const char* typname, void* typeid) {
7483
PyTypeObject* ptype = (PyTypeObject*)UPCALL_CEXT_O(polyglot_from_string("PyTruffle_Type", SRC_CS), polyglot_from_string(typname, SRC_CS));
7584

@@ -201,7 +210,7 @@ void* native_to_java(PyObject* obj) {
201210
} else if (polyglot_is_string(obj)) {
202211
return obj;
203212
} else if (truffle_is_handle_to_managed(obj)) {
204-
return truffle_managed_from_handle(obj);
213+
return resolve_handle(cache, (uint64_t)obj);
205214
} else if (truffle_is_handle_to_managed(obj->ob_refcnt)) {
206215
return truffle_managed_from_handle(obj->ob_refcnt);
207216
} else if (IS_POINTER(obj->ob_refcnt)) {
@@ -231,12 +240,12 @@ PyObject* to_sulong(void *o) {
231240
void* get_ob_type(PyObject* obj) {
232241
PyTypeObject* type = obj->ob_type;
233242
if (truffle_is_handle_to_managed(type)) {
234-
return truffle_managed_from_handle(type);
243+
return resolve_handle(cache, (uint64_t)type);
235244
} else {
236245
// we have stored a handle to the Java class in ob_refcnt
237246
void* handle = (void*)((PyObject*)type)->ob_refcnt;
238247
if (truffle_is_handle_to_managed(handle)) {
239-
return truffle_managed_from_handle(handle);
248+
return resolve_handle(cache, (uint64_t)handle);
240249
} else {
241250
// assume handle is a TruffleObject
242251
return handle;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
117117
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
118118
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
119+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
119120
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
120121
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
121122
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -149,6 +150,7 @@
149150
import com.oracle.truffle.api.interop.UnsupportedMessageException;
150151
import com.oracle.truffle.api.interop.UnsupportedTypeException;
151152
import com.oracle.truffle.api.nodes.DirectCallNode;
153+
import com.oracle.truffle.api.nodes.ExplodeLoop;
152154
import com.oracle.truffle.api.nodes.Node;
153155
import com.oracle.truffle.api.nodes.RootNode;
154156
import com.oracle.truffle.api.profiles.BranchProfile;
@@ -1841,4 +1843,88 @@ Object doIt(Object object,
18411843
return wrapper;
18421844
}
18431845
}
1846+
1847+
private static class HandleCacheEntry {
1848+
private long key;
1849+
private Object value;
1850+
}
1851+
1852+
static class HandleCache implements TruffleObject {
1853+
private static final int CACHE_SIZE = 10;
1854+
1855+
private final HandleCacheEntry[] entries;
1856+
private final TruffleObject ptrToResolveHandle;
1857+
1858+
private int pos = 0;
1859+
1860+
public HandleCache(TruffleObject ptrToResolveHandle) {
1861+
entries = new HandleCacheEntry[CACHE_SIZE];
1862+
for (int i = 0; i < entries.length; i++) {
1863+
entries[i] = new HandleCacheEntry();
1864+
}
1865+
this.ptrToResolveHandle = ptrToResolveHandle;
1866+
}
1867+
1868+
protected int len() {
1869+
return entries.length;
1870+
}
1871+
1872+
protected TruffleObject getPtrToResolveHandle() {
1873+
return ptrToResolveHandle;
1874+
}
1875+
1876+
public ForeignAccess getForeignAccess() {
1877+
return null;
1878+
}
1879+
}
1880+
1881+
@Builtin(name = "PyTruffle_HandleCache_Create", fixedNumOfPositionalArgs = 1)
1882+
@GenerateNodeFactory
1883+
abstract static class PyTruffleHandleCacheCreate extends PythonUnaryBuiltinNode {
1884+
@Specialization
1885+
Object createCache(TruffleObject ptrToResolveHandle) {
1886+
return new HandleCache(ptrToResolveHandle);
1887+
}
1888+
}
1889+
1890+
@Builtin(name = "PyTruffle_HandleCache_GetOrInsert", fixedNumOfPositionalArgs = 2)
1891+
@GenerateNodeFactory
1892+
abstract static class PyTruffleHandleCacheGetOrInsert extends PythonBinaryBuiltinNode {
1893+
@Child private Node executeNode;
1894+
1895+
private final BranchProfile errorProfile = BranchProfile.create();
1896+
1897+
@ExplodeLoop
1898+
@Specialization(limit = "1", guards = {"cache.len() == cachedLen", "cache.getPtrToResolveHandle() == ptrToResolveHandle"})
1899+
Object doIt(HandleCache cache, long handle,
1900+
@Cached("cache.len()") int cachedLen,
1901+
@Cached("cache.getPtrToResolveHandle()") TruffleObject ptrToResolveHandle) {
1902+
for (int i = 0; i < cachedLen; i++) {
1903+
if (cache.entries[i].key == handle) {
1904+
return cache.entries[i].value;
1905+
}
1906+
}
1907+
1908+
try {
1909+
Object resolved = ForeignAccess.sendExecute(getExecuteNode(), ptrToResolveHandle, handle);
1910+
1911+
cache.entries[cache.pos].key = handle;
1912+
cache.entries[cache.pos].value = resolved;
1913+
cache.pos = (cache.pos + 1) % cache.len();
1914+
1915+
return resolved;
1916+
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
1917+
errorProfile.enter();
1918+
throw e.raise();
1919+
}
1920+
}
1921+
1922+
private Node getExecuteNode() {
1923+
if (executeNode == null) {
1924+
CompilerDirectives.transferToInterpreterAndInvalidate();
1925+
executeNode = insert(Message.EXECUTE.createNode());
1926+
}
1927+
return executeNode;
1928+
}
1929+
}
18441930
}

0 commit comments

Comments
 (0)