The community edition of the Truffle runtime providing execution engine and optimization support for dynamic programming languages built with the Truffle framework
—
Extensible SPI system allowing customization of runtime behaviors including loop node creation, engine caching, flood control, and type system integration.
Service provider interface for creating custom loop node implementations.
/**
* Factory for creating optimized loop nodes
* Implement this interface to provide custom loop optimization strategies
*/
public interface LoopNodeFactory {
/**
* Creates a loop node for the given repeating node
* @param repeatingNode The node that will be repeated in the loop
* @return Optimized loop node implementation
*/
LoopNode createLoopNode(RepeatingNode repeatingNode);
/**
* Returns the priority of this factory (higher priority takes precedence)
* @return Priority value, default is 0
*/
default int getPriority() {
return 0;
}
}Usage Examples:
// Custom loop node factory implementation
public class MyCustomLoopNodeFactory implements LoopNodeFactory {
@Override
public LoopNode createLoopNode(RepeatingNode repeatingNode) {
return new MyOptimizedLoopNode(repeatingNode);
}
@Override
public int getPriority() {
return 100; // Higher priority than default
}
}
// Register via META-INF/services/com.oracle.truffle.runtime.LoopNodeFactoryService provider interface for implementing custom engine-level caching strategies.
/**
* Support for engine-level caching of compilation artifacts and metadata
* Implement this interface to provide custom caching strategies
*/
public interface EngineCacheSupport {
/**
* Gets or creates a cached value for the given key
* @param key Cache key (typically related to code structure)
* @param valueSupplier Supplier to create value if not cached
* @return Cached or newly created value
*/
<T> T getEngineCache(Object key, Supplier<T> valueSupplier);
/**
* Clears all cached values for this engine
*/
void clearEngineCache();
/**
* Gets cache statistics if available
* @return Cache statistics or null if not supported
*/
default CacheStatistics getStatistics() {
return null;
}
/**
* Returns the maximum cache size
* @return Maximum number of entries or -1 if unlimited
*/
default long getMaxCacheSize() {
return -1;
}
}Usage Examples:
public class MyEngineCacheSupport implements EngineCacheSupport {
private final ConcurrentHashMap<Object, Object> cache = new ConcurrentHashMap<>();
@Override
public <T> T getEngineCache(Object key, Supplier<T> valueSupplier) {
return (T) cache.computeIfAbsent(key, k -> valueSupplier.get());
}
@Override
public void clearEngineCache() {
cache.clear();
}
@Override
public long getMaxCacheSize() {
return 10000;
}
}Service provider interface for integrating custom type systems with the runtime.
/**
* Integration point for custom type systems
* Allows languages to provide type information to the runtime
*/
public interface TruffleTypes {
/**
* Returns the Java class for a language value
* @param value Language-specific value
* @return Corresponding Java class
*/
Class<?> getJavaClass(Object value);
/**
* Returns the Java class name for a language value
* @param value Language-specific value
* @return Java class name string
*/
String getJavaClassName(Object value);
/**
* Checks if a value is of a specific type
* @param value Value to check
* @param type Type to check against
* @return True if value is of the specified type
*/
default boolean isType(Object value, Class<?> type) {
return type.isInstance(value);
}
/**
* Converts a value to a specific type if possible
* @param value Value to convert
* @param targetType Target type
* @return Converted value or null if conversion not possible
*/
default <T> T convertTo(Object value, Class<T> targetType) {
if (targetType.isInstance(value)) {
return targetType.cast(value);
}
return null;
}
}Usage Examples:
public class MyLanguageTypes implements TruffleTypes {
@Override
public Class<?> getJavaClass(Object value) {
if (value instanceof MyLanguageNumber) {
return Number.class;
} else if (value instanceof MyLanguageString) {
return String.class;
}
return Object.class;
}
@Override
public String getJavaClassName(Object value) {
return getJavaClass(value).getName();
}
@Override
public <T> T convertTo(Object value, Class<T> targetType) {
if (value instanceof MyLanguageNumber && targetType == Integer.class) {
return targetType.cast(((MyLanguageNumber) value).intValue());
}
return TruffleTypes.super.convertTo(value, targetType);
}
}Service provider interface for implementing custom flood control strategies to manage compilation load.
/**
* Handler for managing compilation flood control
* Implement to provide custom strategies for managing compilation load
*/
public interface FloodControlHandler {
/**
* Checks if compilation should be allowed for the given call target
* @param callTarget The call target requesting compilation
* @return True if compilation should proceed, false to defer
*/
boolean allowCompilation(OptimizedCallTarget callTarget);
/**
* Notifies that a compilation request was deferred
* @param callTarget The call target that was deferred
* @param reason Reason for deferral
*/
default void onCompilationDeferred(OptimizedCallTarget callTarget, String reason) {
// Default implementation does nothing
}
/**
* Notifies that compilation started for a call target
* @param callTarget The call target being compiled
*/
default void onCompilationStarted(OptimizedCallTarget callTarget) {
// Default implementation does nothing
}
/**
* Notifies that compilation finished for a call target
* @param callTarget The call target that finished compilation
* @param success True if compilation was successful
*/
default void onCompilationFinished(OptimizedCallTarget callTarget, boolean success) {
// Default implementation does nothing
}
/**
* Returns the current compilation load (0.0 to 1.0)
* @return Load factor where 1.0 means fully loaded
*/
default double getCurrentLoad() {
return 0.0;
}
}Usage Examples:
public class MyFloodControlHandler implements FloodControlHandler {
private final AtomicInteger activeCompilations = new AtomicInteger();
private static final int MAX_CONCURRENT_COMPILATIONS = 4;
@Override
public boolean allowCompilation(OptimizedCallTarget callTarget) {
int current = activeCompilations.get();
if (current >= MAX_CONCURRENT_COMPILATIONS) {
return false;
}
return activeCompilations.compareAndSet(current, current + 1);
}
@Override
public void onCompilationFinished(OptimizedCallTarget callTarget, boolean success) {
activeCompilations.decrementAndGet();
}
@Override
public double getCurrentLoad() {
return (double) activeCompilations.get() / MAX_CONCURRENT_COMPILATIONS;
}
}All service providers are registered using Java's ServiceLoader mechanism.
Service Files:
Create these files in META-INF/services/:
com.oracle.truffle.runtime.LoopNodeFactorycom.oracle.truffle.runtime.EngineCacheSupportcom.oracle.truffle.runtime.TruffleTypescom.oracle.truffle.runtime.FloodControlHandlerEach file should contain the fully qualified class name of your implementation:
com.example.MyCustomLoopNodeFactory
com.example.MyEngineCacheSupport
com.example.MyLanguageTypes
com.example.MyFloodControlHandlerProgrammatic Access:
// Access services through the runtime
TruffleRuntime runtime = Truffle.getRuntime();
// Services are automatically discovered and used by the runtime
// No direct API for accessing individual servicespublic interface CacheStatistics {
/** Returns the number of cache hits */
long getHitCount();
/** Returns the number of cache misses */
long getMissCount();
/** Returns the current number of cached entries */
long getSize();
/** Returns the cache hit rate (0.0 to 1.0) */
double getHitRate();
/** Returns the average time to load a value (in nanoseconds) */
double getAverageLoadTime();
}
public interface Supplier<T> {
/** Gets a result */
T get();
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-truffle--truffle-runtime