use of com.oracle.truffle.dsl.processor.library.LibraryData in project graal by oracle.
the class NodeParser method parseCachedLibraries.
private SpecializationData parseCachedLibraries(SpecializationData specialization, DSLExpressionResolver resolver, List<CacheExpression> libraries) {
SpecializationData uncachedSpecialization = null;
List<CacheExpression> uncachedLibraries = null;
/*
* No uncached specialization needed if there is a specialization that is strictly more
* generic than this one.
*/
if (!specialization.isReplaced()) {
uncachedSpecialization = specialization.copy();
uncachedLibraries = new ArrayList<>();
uncachedSpecialization.getReplaces().add(specialization);
List<CacheExpression> caches = uncachedSpecialization.getCaches();
for (int i = 0; i < caches.size(); i++) {
CacheExpression expression = caches.get(i);
if (expression.getCachedLibraryExpression() != null) {
expression = expression.copy();
caches.set(i, expression);
uncachedLibraries.add(expression);
}
}
specialization.setUncachedSpecialization(uncachedSpecialization);
}
if (uncachedLibraries != null && uncachedLibraries.size() != libraries.size()) {
throw new AssertionError("Unexpected number of uncached libraries.");
}
boolean seenDynamicParameterBound = false;
for (int i = 0; i < libraries.size(); i++) {
CacheExpression cachedLibrary = libraries.get(i);
CacheExpression uncachedLibrary = uncachedLibraries != null ? uncachedLibraries.get(i) : null;
TypeMirror parameterType = cachedLibrary.getParameter().getType();
TypeElement type = ElementUtils.fromTypeMirror(parameterType);
if (type == null) {
cachedLibrary.addError("Invalid library type %s. Must be a declared type.", getSimpleName(parameterType));
continue;
}
if (!ElementUtils.isAssignable(parameterType, types.Library)) {
cachedLibrary.addError("Invalid library type %s. Library is not a subclass of %s.", getSimpleName(parameterType), types.Library.asElement().getSimpleName().toString());
continue;
}
if (ElementUtils.findAnnotationMirror(cachedLibrary.getParameter().getVariableElement(), types.Cached_Shared) != null) {
cachedLibrary.addError("Specialized cached libraries cannot be shared yet.");
continue;
}
Map<TypeElement, LibraryData> libraryCache = ProcessorContext.getInstance().getCacheMap(LibraryParser.class);
LibraryData parsedLibrary = libraryCache.computeIfAbsent(type, (t) -> new LibraryParser().parse(t));
if (parsedLibrary == null || parsedLibrary.hasErrors()) {
cachedLibrary.addError("Library '%s' has errors. Please resolve them first.", getSimpleName(parameterType));
continue;
}
cachedLibrary.setCachedLibrary(parsedLibrary);
if (uncachedLibrary != null) {
uncachedLibrary.setCachedLibrary(parsedLibrary);
}
String expression = cachedLibrary.getCachedLibraryExpression();
DSLExpression receiverExpression = parseCachedExpression(resolver, cachedLibrary, parsedLibrary.getSignatureReceiverType(), expression);
if (receiverExpression == null) {
continue;
}
DSLExpression substituteCachedExpression = null;
DSLExpression substituteUncachedExpression = null;
// try substitutions
if (mode == ParseMode.EXPORTED_MESSAGE) {
Parameter receiverParameter = specialization.findParameterOrDie(specialization.getNode().getChildExecutions().get(0));
if (receiverExpression instanceof DSLExpression.Variable) {
DSLExpression.Variable variable = (DSLExpression.Variable) receiverExpression;
if (variable.getReceiver() == null) {
VariableElement resolvedVariable = variable.getResolvedVariable();
if (ElementUtils.variableEquals(resolvedVariable, receiverParameter.getVariableElement())) {
// receiver
if (typeEquals(type.asType(), exportLibraryType)) {
DSLExpression.Variable nodeReceiver = new DSLExpression.Variable(null, "this");
nodeReceiver.setResolvedTargetType(exportLibraryType);
nodeReceiver.setResolvedVariable(new CodeVariableElement(exportLibraryType, "this"));
if (substituteThisToParent) {
DSLExpression.Call call = new DSLExpression.Call(nodeReceiver, "getParent", Collections.emptyList());
call.setResolvedMethod(ElementUtils.findMethod(types.Node, "getParent"));
call.setResolvedTargetType(context.getType(Object.class));
substituteCachedExpression = new DSLExpression.Cast(call, exportLibraryType);
} else {
substituteCachedExpression = nodeReceiver;
}
}
}
}
}
if (substituteCachedExpression == null && supportsLibraryMerge(receiverExpression, receiverParameter.getVariableElement())) {
substituteCachedExpression = receiverExpression;
cachedLibrary.setMergedLibrary(true);
}
}
if (substituteCachedExpression != null) {
if (substituteUncachedExpression == null) {
substituteUncachedExpression = substituteCachedExpression;
}
cachedLibrary.setDefaultExpression(substituteCachedExpression);
cachedLibrary.setUncachedExpression(substituteUncachedExpression);
cachedLibrary.setAlwaysInitialized(true);
continue;
} else {
seenDynamicParameterBound |= specialization.isDynamicParameterBound(receiverExpression, true);
cachedLibrary.setDefaultExpression(receiverExpression);
String receiverName = cachedLibrary.getParameter().getVariableElement().getSimpleName().toString();
DSLExpression acceptGuard = new DSLExpression.Call(new DSLExpression.Variable(null, receiverName), "accepts", Arrays.asList(receiverExpression));
acceptGuard = resolveCachedExpression(resolver, cachedLibrary, context.getType(boolean.class), acceptGuard, expression);
if (acceptGuard != null) {
GuardExpression guard = new GuardExpression(specialization, acceptGuard);
guard.setLibraryAcceptsGuard(true);
specialization.getGuards().add(guard);
}
TypeMirror libraryType = types.Library;
TypeMirror usedLibraryType = parameterType;
DSLExpression resolveCall = new DSLExpression.Call(null, "resolve", Arrays.asList(new DSLExpression.ClassLiteral(usedLibraryType)));
DSLExpressionResolver cachedResolver = importStatics(resolver, types.LibraryFactory);
DSLExpression defaultExpression = new DSLExpression.Call(resolveCall, "create", Arrays.asList(receiverExpression));
defaultExpression = resolveCachedExpression(cachedResolver, cachedLibrary, libraryType, defaultExpression, expression);
cachedLibrary.setDefaultExpression(defaultExpression);
DSLExpression uncachedExpression = new DSLExpression.Call(resolveCall, "getUncached", Arrays.asList(receiverExpression));
cachedLibrary.setUncachedExpression(uncachedExpression);
uncachedExpression = resolveCachedExpression(cachedResolver, cachedLibrary, libraryType, uncachedExpression, expression);
if (uncachedLibrary != null) {
uncachedLibrary.setDefaultExpression(uncachedExpression);
uncachedLibrary.setUncachedExpression(uncachedExpression);
uncachedLibrary.setAlwaysInitialized(true);
uncachedLibrary.setRequiresBoundary(true);
}
}
}
if (specialization.isFallback()) {
for (int i = 0; i < libraries.size(); i++) {
CacheExpression cachedLibrary = libraries.get(i);
if (cachedLibrary.getCachedLibraryExpression() != null) {
cachedLibrary.addError("@%s annotations with specialized receivers are not supported in combination with @%s annotations. " + "Specify the @%s(limit=\"...\") attribute and remove the receiver expression to use an dispatched library instead.", getSimpleName(types.CachedLibrary), getSimpleName(types.Fallback), getSimpleName(types.CachedLibrary));
}
}
}
if (!libraries.isEmpty() && !specialization.hasErrors() && ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "limit", false) == null && specialization.hasMultipleInstances()) {
specialization.addError("The limit attribute must be specified if @%s is used with a dynamic parameter. E.g. add limit=\"3\" to resolve this.", types.CachedLibrary.asElement().getSimpleName().toString());
}
if (!seenDynamicParameterBound) {
// bound by a cache only.
return null;
}
return uncachedSpecialization;
}
Aggregations