com.oracle.truffle.api.dsl.Introspection Maven / Gradle / Ivy
Show all versions of truffle-api Show documentation
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.dsl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.oracle.truffle.api.dsl.Introspection.SpecializationInfo;
import com.oracle.truffle.api.nodes.Node;
/**
* Contains introspection utilities for Truffle DSL. The contained utilities are only usable if the
* operation node is annotated with {@link Introspectable}.
*
* Introspection is useful for using testing the node declaration and verifying that particular
* specializations become active.
*
* Example for using introspection in unit testing:
*
* {@codesnippet com.oracle.truffle.api.dsl.IntrospectionSnippets.NegateNode}
*
* @since 0.22
* @see Introspectable
*/
public final class Introspection {
private static final List> EMPTY_CACHED = Collections.unmodifiableList(Arrays.asList(Collections.emptyList()));
private static final List> NO_CACHED = Collections.emptyList();
private final Object[] data;
Introspection(Object[] data) {
this.data = data;
}
/**
* Returns true
if the given node is introspectable. If something is introspectable
* is determined by if the node is generated by Truffle DSL, if is annotated with
* {@link Introspectable} and if the DSL implementation supports introspection.
*
* @param node a DSL generated node
* @return true if the given node is introspectable
* @since 0.22
*/
public static boolean isIntrospectable(Node node) {
return node instanceof Provider;
}
/**
* Returns introspection information for the first specialization that matches a given method
* name. A node must declare at least one specialization and must be annotated with
* {@link Introspectable} otherwise an {@link IllegalArgumentException} is thrown. If multiple
* specializations with the same method name are declared then an undefined specialization is
* going to be returned. In such cases disambiguate them by renaming the specialzation method
* name. The returned introspection information is not updated when the state of the given
* operation node is updated. The implementation of this method might be slow, do not use it in
* performance critical code.
*
* @param node a introspectable DSL operation with at least one specialization
* @param methodName the Java method name of the specialization to introspect
* @return introspection info for the method
* @see Introspection example usage
* @since 0.22
*/
public static SpecializationInfo getSpecialization(Node node, String methodName) {
return getIntrospectionData(node).getSpecialization(methodName);
}
/**
* Returns introspection information for all declared specializations as unmodifiable list. A
* given node must declare at least one specialization and must be annotated with
* {@link Introspectable} otherwise an {@link IllegalArgumentException} is thrown. The returned
* introspection information is not updated when the state of the given operation node is
* updated. The implementation of this method might be slow, do not use it in performance
* critical code.
*
* @param node a introspectable DSL operation with at least one specialization
* @see Introspection example usage
* @since 0.22
*/
public static List getSpecializations(Node node) {
return getIntrospectionData(node).getSpecializations();
}
private static Introspection getIntrospectionData(Node node) {
if (!(node instanceof Provider)) {
throw new IllegalArgumentException(String.format("Provided node is not introspectable. Annotate with @%s to make a node introspectable.", Introspectable.class.getSimpleName()));
}
return ((Provider) node).getIntrospectionData();
}
/**
* Represents dynamic introspection information of a specialization of a DSL operation.
*
* @since 0.22
*/
public static final class SpecializationInfo {
private final String methodName;
private final byte state; /* 0b000000 */
private final List> cachedData;
SpecializationInfo(String methodName, byte state, List> cachedData) {
this.methodName = methodName;
this.state = state;
this.cachedData = cachedData;
}
/**
* Returns the method name of the introspected specialization. Please note that the returned
* method name might not be unique for a given node.
*
* @since 0.22
*/
public String getMethodName() {
return methodName;
}
/**
* Returns true
if the specialization was active at the time when the
* introspection was performed.
*
* @since 0.22
*/
public boolean isActive() {
return (state & 0b1) != 0;
}
/**
* Returns true
if the specialization was excluded at the time when the
* introspection was performed.
*
* @since 0.22
*/
public boolean isExcluded() {
return (state & 0b10) != 0;
}
/**
* Returns the number of dynamic specialization instances that are active for this
* specialization.
*
* @since 0.22
*/
public int getInstances() {
return cachedData.size();
}
/**
* Returns the cached state for a given specialization instance. The provided instance index
* must be greater or equal 0
and smaller {@link #getInstances()}. The returned
* list is unmodifiable and never null
.
*
* @since 0.22
*/
public List