|
3 | 3 | import com.oracle.graal.python.builtins.objects.cext.HandleCacheFactory.HandleCacheMRFactory.GetOrInsertNodeGen;
|
4 | 4 | import com.oracle.truffle.api.CompilerDirectives;
|
5 | 5 | import com.oracle.truffle.api.dsl.Cached;
|
| 6 | +import com.oracle.truffle.api.dsl.ImportStatic; |
6 | 7 | import com.oracle.truffle.api.dsl.Specialization;
|
7 | 8 | import com.oracle.truffle.api.interop.ArityException;
|
8 | 9 | import com.oracle.truffle.api.interop.ForeignAccess;
|
|
12 | 13 | import com.oracle.truffle.api.interop.TruffleObject;
|
13 | 14 | import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
14 | 15 | import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
| 16 | +import com.oracle.truffle.api.nodes.ControlFlowException; |
15 | 17 | import com.oracle.truffle.api.nodes.ExplodeLoop;
|
16 | 18 | import com.oracle.truffle.api.nodes.Node;
|
17 | 19 | import com.oracle.truffle.api.profiles.BranchProfile;
|
18 | 20 |
|
19 | 21 | public final class HandleCache implements TruffleObject {
|
20 |
| - private static final int CACHE_SIZE = 10; |
| 22 | + public static final int CACHE_SIZE = 10; |
21 | 23 |
|
22 | 24 | final long[] keys;
|
23 | 25 | final Object[] values;
|
@@ -66,32 +68,57 @@ Object access(HandleCache receiver, Object[] args) {
|
66 | 68 |
|
67 | 69 | }
|
68 | 70 |
|
| 71 | + static class InvalidCacheEntryException extends ControlFlowException { |
| 72 | + private static final long serialVersionUID = 1L; |
| 73 | + public static final InvalidCacheEntryException INSTANCE = new InvalidCacheEntryException(); |
| 74 | + } |
| 75 | + |
| 76 | + @ImportStatic(HandleCache.class) |
69 | 77 | abstract static class GetOrInsertNode extends Node {
|
70 | 78 | @Child private Node executeNode;
|
71 | 79 |
|
72 | 80 | private final BranchProfile errorProfile = BranchProfile.create();
|
73 | 81 |
|
74 | 82 | public abstract Object execute(HandleCache cache, long handle);
|
75 | 83 |
|
76 |
| - @ExplodeLoop |
77 |
| - @Specialization(guards = {"cache.len() == cachedLen", "cache.getPtrToResolveHandle() == ptrToResolveHandle"}) |
78 |
| - Object doIt(HandleCache cache, long handle, |
| 84 | + @Specialization(limit = "CACHE_SIZE", guards = {"cache.len() == cachedLen", |
| 85 | + "handle == cachedHandle"}, rewriteOn = InvalidCacheEntryException.class) |
| 86 | + Object doCached(HandleCache cache, @SuppressWarnings("unused") long handle, |
| 87 | + @Cached("handle") long cachedHandle, |
| 88 | + @Cached("cache.len()") @SuppressWarnings("unused") int cachedLen, |
| 89 | + @Cached("cache.getPtrToResolveHandle()") @SuppressWarnings("unused") TruffleObject ptrToResolveHandle, |
| 90 | + @Cached("lookupPosition(cache, handle, cachedLen, ptrToResolveHandle)") int cachedPosition) throws InvalidCacheEntryException { |
| 91 | + if (cache.keys[cachedPosition] == cachedHandle) { |
| 92 | + return cache.values[cachedPosition]; |
| 93 | + } |
| 94 | + throw InvalidCacheEntryException.INSTANCE; |
| 95 | + } |
| 96 | + |
| 97 | + @Specialization(guards = {"cache.len() == cachedLen"}, replaces = "doCached") |
| 98 | + Object doFullLookup(HandleCache cache, long handle, |
79 | 99 | @Cached("cache.len()") int cachedLen,
|
80 | 100 | @Cached("cache.getPtrToResolveHandle()") TruffleObject ptrToResolveHandle) {
|
| 101 | + int pos = lookupPosition(cache, handle, cachedLen, ptrToResolveHandle); |
| 102 | + return cache.values[pos]; |
| 103 | + } |
| 104 | + |
| 105 | + @ExplodeLoop |
| 106 | + protected int lookupPosition(HandleCache cache, long handle, int cachedLen, TruffleObject ptrToResolveHandle) { |
81 | 107 | for (int i = 0; i < cachedLen; i++) {
|
82 | 108 | if (cache.keys[i] == handle) {
|
83 |
| - return cache.values[i]; |
| 109 | + return i; |
84 | 110 | }
|
85 | 111 | }
|
86 | 112 |
|
87 | 113 | try {
|
88 | 114 | Object resolved = ForeignAccess.sendExecute(getExecuteNode(), ptrToResolveHandle, handle);
|
89 | 115 |
|
90 |
| - cache.keys[cache.pos] = handle; |
91 |
| - cache.values[cache.pos] = resolved; |
92 |
| - cache.pos = (cache.pos + 1) % cache.len(); |
| 116 | + int insertPos = cache.pos; |
| 117 | + cache.keys[insertPos] = handle; |
| 118 | + cache.values[insertPos] = resolved; |
| 119 | + cache.pos = (insertPos + 1) % cache.len(); |
93 | 120 |
|
94 |
| - return resolved; |
| 121 | + return insertPos; |
95 | 122 | } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
|
96 | 123 | errorProfile.enter();
|
97 | 124 | throw e.raise();
|
|
0 commit comments