0
# Service Provider Framework
1
2
Extensible SPI system allowing customization of runtime behaviors including loop node creation, engine caching, flood control, and type system integration.
3
4
## Capabilities
5
6
### LoopNodeFactory
7
8
Service provider interface for creating custom loop node implementations.
9
10
```java { .api }
11
/**
12
* Factory for creating optimized loop nodes
13
* Implement this interface to provide custom loop optimization strategies
14
*/
15
public interface LoopNodeFactory {
16
/**
17
* Creates a loop node for the given repeating node
18
* @param repeatingNode The node that will be repeated in the loop
19
* @return Optimized loop node implementation
20
*/
21
LoopNode createLoopNode(RepeatingNode repeatingNode);
22
23
/**
24
* Returns the priority of this factory (higher priority takes precedence)
25
* @return Priority value, default is 0
26
*/
27
default int getPriority() {
28
return 0;
29
}
30
}
31
```
32
33
**Usage Examples:**
34
35
```java
36
// Custom loop node factory implementation
37
public class MyCustomLoopNodeFactory implements LoopNodeFactory {
38
39
@Override
40
public LoopNode createLoopNode(RepeatingNode repeatingNode) {
41
return new MyOptimizedLoopNode(repeatingNode);
42
}
43
44
@Override
45
public int getPriority() {
46
return 100; // Higher priority than default
47
}
48
}
49
50
// Register via META-INF/services/com.oracle.truffle.runtime.LoopNodeFactory
51
```
52
53
### EngineCacheSupport
54
55
Service provider interface for implementing custom engine-level caching strategies.
56
57
```java { .api }
58
/**
59
* Support for engine-level caching of compilation artifacts and metadata
60
* Implement this interface to provide custom caching strategies
61
*/
62
public interface EngineCacheSupport {
63
/**
64
* Gets or creates a cached value for the given key
65
* @param key Cache key (typically related to code structure)
66
* @param valueSupplier Supplier to create value if not cached
67
* @return Cached or newly created value
68
*/
69
<T> T getEngineCache(Object key, Supplier<T> valueSupplier);
70
71
/**
72
* Clears all cached values for this engine
73
*/
74
void clearEngineCache();
75
76
/**
77
* Gets cache statistics if available
78
* @return Cache statistics or null if not supported
79
*/
80
default CacheStatistics getStatistics() {
81
return null;
82
}
83
84
/**
85
* Returns the maximum cache size
86
* @return Maximum number of entries or -1 if unlimited
87
*/
88
default long getMaxCacheSize() {
89
return -1;
90
}
91
}
92
```
93
94
**Usage Examples:**
95
96
```java
97
public class MyEngineCacheSupport implements EngineCacheSupport {
98
private final ConcurrentHashMap<Object, Object> cache = new ConcurrentHashMap<>();
99
100
@Override
101
public <T> T getEngineCache(Object key, Supplier<T> valueSupplier) {
102
return (T) cache.computeIfAbsent(key, k -> valueSupplier.get());
103
}
104
105
@Override
106
public void clearEngineCache() {
107
cache.clear();
108
}
109
110
@Override
111
public long getMaxCacheSize() {
112
return 10000;
113
}
114
}
115
```
116
117
### TruffleTypes
118
119
Service provider interface for integrating custom type systems with the runtime.
120
121
```java { .api }
122
/**
123
* Integration point for custom type systems
124
* Allows languages to provide type information to the runtime
125
*/
126
public interface TruffleTypes {
127
/**
128
* Returns the Java class for a language value
129
* @param value Language-specific value
130
* @return Corresponding Java class
131
*/
132
Class<?> getJavaClass(Object value);
133
134
/**
135
* Returns the Java class name for a language value
136
* @param value Language-specific value
137
* @return Java class name string
138
*/
139
String getJavaClassName(Object value);
140
141
/**
142
* Checks if a value is of a specific type
143
* @param value Value to check
144
* @param type Type to check against
145
* @return True if value is of the specified type
146
*/
147
default boolean isType(Object value, Class<?> type) {
148
return type.isInstance(value);
149
}
150
151
/**
152
* Converts a value to a specific type if possible
153
* @param value Value to convert
154
* @param targetType Target type
155
* @return Converted value or null if conversion not possible
156
*/
157
default <T> T convertTo(Object value, Class<T> targetType) {
158
if (targetType.isInstance(value)) {
159
return targetType.cast(value);
160
}
161
return null;
162
}
163
}
164
```
165
166
**Usage Examples:**
167
168
```java
169
public class MyLanguageTypes implements TruffleTypes {
170
171
@Override
172
public Class<?> getJavaClass(Object value) {
173
if (value instanceof MyLanguageNumber) {
174
return Number.class;
175
} else if (value instanceof MyLanguageString) {
176
return String.class;
177
}
178
return Object.class;
179
}
180
181
@Override
182
public String getJavaClassName(Object value) {
183
return getJavaClass(value).getName();
184
}
185
186
@Override
187
public <T> T convertTo(Object value, Class<T> targetType) {
188
if (value instanceof MyLanguageNumber && targetType == Integer.class) {
189
return targetType.cast(((MyLanguageNumber) value).intValue());
190
}
191
return TruffleTypes.super.convertTo(value, targetType);
192
}
193
}
194
```
195
196
### FloodControlHandler
197
198
Service provider interface for implementing custom flood control strategies to manage compilation load.
199
200
```java { .api }
201
/**
202
* Handler for managing compilation flood control
203
* Implement to provide custom strategies for managing compilation load
204
*/
205
public interface FloodControlHandler {
206
/**
207
* Checks if compilation should be allowed for the given call target
208
* @param callTarget The call target requesting compilation
209
* @return True if compilation should proceed, false to defer
210
*/
211
boolean allowCompilation(OptimizedCallTarget callTarget);
212
213
/**
214
* Notifies that a compilation request was deferred
215
* @param callTarget The call target that was deferred
216
* @param reason Reason for deferral
217
*/
218
default void onCompilationDeferred(OptimizedCallTarget callTarget, String reason) {
219
// Default implementation does nothing
220
}
221
222
/**
223
* Notifies that compilation started for a call target
224
* @param callTarget The call target being compiled
225
*/
226
default void onCompilationStarted(OptimizedCallTarget callTarget) {
227
// Default implementation does nothing
228
}
229
230
/**
231
* Notifies that compilation finished for a call target
232
* @param callTarget The call target that finished compilation
233
* @param success True if compilation was successful
234
*/
235
default void onCompilationFinished(OptimizedCallTarget callTarget, boolean success) {
236
// Default implementation does nothing
237
}
238
239
/**
240
* Returns the current compilation load (0.0 to 1.0)
241
* @return Load factor where 1.0 means fully loaded
242
*/
243
default double getCurrentLoad() {
244
return 0.0;
245
}
246
}
247
```
248
249
**Usage Examples:**
250
251
```java
252
public class MyFloodControlHandler implements FloodControlHandler {
253
private final AtomicInteger activeCompilations = new AtomicInteger();
254
private static final int MAX_CONCURRENT_COMPILATIONS = 4;
255
256
@Override
257
public boolean allowCompilation(OptimizedCallTarget callTarget) {
258
int current = activeCompilations.get();
259
if (current >= MAX_CONCURRENT_COMPILATIONS) {
260
return false;
261
}
262
return activeCompilations.compareAndSet(current, current + 1);
263
}
264
265
@Override
266
public void onCompilationFinished(OptimizedCallTarget callTarget, boolean success) {
267
activeCompilations.decrementAndGet();
268
}
269
270
@Override
271
public double getCurrentLoad() {
272
return (double) activeCompilations.get() / MAX_CONCURRENT_COMPILATIONS;
273
}
274
}
275
```
276
277
### Service Registration
278
279
All service providers are registered using Java's ServiceLoader mechanism.
280
281
**Service Files:**
282
283
Create these files in `META-INF/services/`:
284
285
- `com.oracle.truffle.runtime.LoopNodeFactory`
286
- `com.oracle.truffle.runtime.EngineCacheSupport`
287
- `com.oracle.truffle.runtime.TruffleTypes`
288
- `com.oracle.truffle.runtime.FloodControlHandler`
289
290
Each file should contain the fully qualified class name of your implementation:
291
292
```
293
com.example.MyCustomLoopNodeFactory
294
com.example.MyEngineCacheSupport
295
com.example.MyLanguageTypes
296
com.example.MyFloodControlHandler
297
```
298
299
**Programmatic Access:**
300
301
```java
302
// Access services through the runtime
303
TruffleRuntime runtime = Truffle.getRuntime();
304
305
// Services are automatically discovered and used by the runtime
306
// No direct API for accessing individual services
307
```
308
309
## Common Types
310
311
```java { .api }
312
public interface CacheStatistics {
313
/** Returns the number of cache hits */
314
long getHitCount();
315
316
/** Returns the number of cache misses */
317
long getMissCount();
318
319
/** Returns the current number of cached entries */
320
long getSize();
321
322
/** Returns the cache hit rate (0.0 to 1.0) */
323
double getHitRate();
324
325
/** Returns the average time to load a value (in nanoseconds) */
326
double getAverageLoadTime();
327
}
328
329
public interface Supplier<T> {
330
/** Gets a result */
331
T get();
332
}
333
```