/*
* 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.
*
* 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.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import org.junit.Test;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Introspectable;
import com.oracle.truffle.api.dsl.Introspection;
import com.oracle.truffle.api.dsl.Introspection.SpecializationInfo;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.TypeSystem;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
import com.oracle.truffle.api.dsl.test.IntrospectionTestFactory.FallbackNodeGen;
import com.oracle.truffle.api.dsl.test.IntrospectionTestFactory.Introspection1NodeGen;
import com.oracle.truffle.api.nodes.Node;
public class IntrospectionTest {
@TypeSystem
public static class IntrospectionTypeSystem {
}
@TypeSystemReference(IntrospectionTypeSystem.class)
@Introspectable
public static class ReflectableNode extends Node {
}
@SuppressWarnings("unused")
@TypeSystemReference(IntrospectionTypeSystem.class)
// BEGIN: com.oracle.truffle.api.dsl.test.IntrospectionTest
@Introspectable
abstract static class NegateNode extends Node {
abstract Object execute(Object o);
@Specialization(guards = "cachedvalue == value", limit = "1")
protected static int doInt(int value,
@Cached("value") int cachedvalue) {
return -cachedvalue;
}
@Specialization(replaces = "doInt")
protected static int doGeneric(int value) {
return -value;
}
}
@Test
public void testUsingIntrospection() {
NegateNode node = IntrospectionTestFactory.NegateNodeGen.create();
SpecializationInfo info;
node.execute(1);
info = Introspection.getSpecialization(node, "doInt");
assertEquals(1, info.getInstances());
node.execute(1);
info = Introspection.getSpecialization(node, "doInt");
assertEquals(1, info.getInstances());
node.execute(2);
info = Introspection.getSpecialization(node, "doInt");
assertEquals(0, info.getInstances());
info = Introspection.getSpecialization(node, "doGeneric");
assertEquals(1, info.getInstances());
}
// END: com.oracle.truffle.api.dsl.test.IntrospectionTest
public abstract static class Introspection1Node extends ReflectableNode {
abstract Object execute(Object o);
@Specialization(guards = "cachedO == o")
protected static int doInt(int o, @SuppressWarnings("unused") @Cached("o") int cachedO) {
return o;
}
@Specialization(replaces = "doInt")
protected static int doGeneric(int o) {
return o;
}
}
@Test
public void testReflection1() {
Introspection1Node node = Introspection1NodeGen.create();
SpecializationInfo specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
try {
assertEquals(0, specialization.getCachedData(0));
fail();
} catch (IllegalArgumentException e) {
}
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
try {
node.execute("");
fail();
} catch (UnsupportedSpecializationException e) {
}
node.execute(1);
specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(1, specialization.getInstances());
assertEquals(1, specialization.getCachedData(0).get(0));
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
node.execute(1);
specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(1, specialization.getInstances());
assertEquals(1, specialization.getCachedData(0).get(0));
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
node.execute(2);
specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(2, specialization.getInstances());
assertEquals(2, specialization.getCachedData(0).get(0));
assertEquals(1, specialization.getCachedData(1).get(0));
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
node.execute(3);
specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(3, specialization.getInstances());
assertEquals(3, specialization.getCachedData(0).get(0));
assertEquals(2, specialization.getCachedData(1).get(0));
assertEquals(1, specialization.getCachedData(2).get(0));
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
node.execute(4);
specialization = Introspection.getSpecialization(node, "doInt");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(0));
assertEquals("doInt", specialization.getMethodName());
assertFalse(specialization.isActive());
assertTrue(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
specialization = Introspection.getSpecialization(node, "doGeneric");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doGeneric", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(1, specialization.getInstances());
assertEquals(0, specialization.getCachedData(0).size());
}
@Test
public void testFallbackReflection() {
FallbackNode node = FallbackNodeGen.create();
SpecializationInfo specialization = Introspection.getSpecialization(node, "doFallback");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doFallback", specialization.getMethodName());
assertFalse(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(0, specialization.getInstances());
node.execute("fallback");
specialization = Introspection.getSpecialization(node, "doFallback");
assertSpecializationEquals(specialization, Introspection.getSpecializations(node).get(1));
assertEquals("doFallback", specialization.getMethodName());
assertTrue(specialization.isActive());
assertFalse(specialization.isExcluded());
assertEquals(1, specialization.getInstances());
}
public abstract static class FallbackNode extends ReflectableNode {
abstract Object execute(Object o);
@Specialization
protected static int doGeneric(int o) {
return o;
}
@Fallback
protected static Object doFallback(Object fallback) {
return fallback;
}
}
private static void assertSpecializationEquals(SpecializationInfo s1, SpecializationInfo s2) {
assertEquals(s1.getMethodName(), s2.getMethodName());
assertEquals(s1.isActive(), s2.isActive());
assertEquals(s1.isExcluded(), s2.isExcluded());
assertEquals(s1.getInstances(), s2.getInstances());
for (int i = 0; i < s1.getInstances(); i++) {
List<Object> cachedData1 = s1.getCachedData(i);
List<Object> cachedData2 = s2.getCachedData(i);
assertEquals(cachedData1.size(), cachedData2.size());
for (int j = 0; j < cachedData1.size(); j++) {
assertEquals(cachedData1.get(j), cachedData2.get(j));
}
}
}
@SuppressWarnings("deprecation")
@com.oracle.truffle.api.dsl.internal.DSLOptions(defaultGenerator = com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator.DEFAULT)
@TypeSystem
public static class SomeReflectionTS {
}
@ExpectError("Reflection is not supported by the used DSL layout. Only the flat DSL layout supports reflection.")
@Introspectable
@TypeSystemReference(SomeReflectionTS.class)
public abstract static class SomeReflection1Node extends Node {
abstract Object execute(Object o);
@Specialization
protected static int doInt(int o) {
return o;
}
}
}