/*
* 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 org.junit.Assert;
import org.junit.Test;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
import com.oracle.truffle.api.dsl.test.IdentityComparisonTestFactory.EqualityComparison1NodeGen;
import com.oracle.truffle.api.dsl.test.IdentityComparisonTestFactory.IdentityComparison1NodeGen;
import com.oracle.truffle.api.dsl.test.examples.ExampleTypes;
import com.oracle.truffle.api.nodes.Node;
public class IdentityComparisonTest {
@Test
public void testIdentityComparison() {
IdentityComparison1Node node = IdentityComparison1NodeGen.create();
Assert.assertEquals(true, node.execute(true));
Assert.assertEquals((byte) 1, node.execute((byte) 1));
Assert.assertEquals((short) 1, node.execute((short) 1));
Assert.assertEquals((char) 1, node.execute((char) 1));
Assert.assertEquals(1, node.execute(1));
Assert.assertEquals(1L, node.execute(1L));
Assert.assertEquals(1f, node.execute(1f));
Assert.assertEquals(1d, node.execute(1d));
// Double.NaN must fail because NaN must not be identity equal to NaN.
// The DSL can optimize the == operator but must be careful with NaN values.
// If the DSL optimizes the == operator it would not throw an unsupported
// specialization exception
try {
node.execute(Double.NaN);
Assert.fail();
} catch (UnsupportedSpecializationException e) {
}
try {
node.execute(Float.NaN);
Assert.fail();
} catch (UnsupportedSpecializationException e) {
}
}
@SuppressWarnings("unused")
@TypeSystemReference(ExampleTypes.class)
abstract static class IdentityComparison1Node extends Node {
public abstract Object execute(Object arg0);
@Specialization(guards = "value == cachedValue")
boolean s0(boolean value, @Cached("value") boolean cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
byte s1(byte value, @Cached("value") byte cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
short s2(short value, @Cached("value") short cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
char s3(char value, @Cached("value") char cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
int s4(int value, @Cached("value") int cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
long s5(long value, @Cached("value") long cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
float s6(float value, @Cached("value") float cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
double s7(double value, @Cached("value") double cachedValue) {
return value;
}
@Specialization(guards = "value == cachedValue")
String s8(String value, @Cached("value") String cachedValue) {
return value;
}
}
@Test
public void testEqualityComparison() {
EqualityComparison1Node node = EqualityComparison1NodeGen.create();
Assert.assertEquals(true, node.execute(true));
Assert.assertEquals((byte) 1, node.execute((byte) 1));
Assert.assertEquals((short) 1, node.execute((short) 1));
Assert.assertEquals((char) 1, node.execute((char) 1));
Assert.assertEquals(1, node.execute(1));
Assert.assertEquals(1L, node.execute(1L));
Assert.assertEquals(1f, node.execute(1f));
Assert.assertEquals(1d, node.execute(1d));
/*
* Equality for equals comparison of NaN can fold.
*/
Assert.assertEquals(Double.NaN, node.execute(Double.NaN));
Assert.assertEquals(Float.NaN, node.execute(Float.NaN));
MyClass myClassValue = new MyClass();
Assert.assertSame(myClassValue, node.execute(myClassValue));
// for the first execution we never need to call equals
Assert.assertEquals(0, myClassValue.equalsCalled);
Assert.assertSame(myClassValue, node.execute(myClassValue));
// the second iteration requires one equals call for the cache
Assert.assertEquals(1, myClassValue.equalsCalled);
}
@SuppressWarnings("unused")
@TypeSystemReference(ExampleTypes.class)
abstract static class EqualityComparison1Node extends Node {
public abstract Object execute(Object arg0);
@Specialization(guards = "value.equals(cachedValue)")
Boolean s0(Boolean value, @Cached("value") Boolean cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Byte s1(Byte value, @Cached("value") Byte cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Short s2(Short value, @Cached("value") Short cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Character s3(Character value, @Cached("value") Character cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Integer s4(Integer value, @Cached("value") Integer cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Long s5(Long value, @Cached("value") Long cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Float s6(Float value, @Cached("value") Float cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
Double s7(Double value, @Cached("value") Double cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
String s8(String value, @Cached("value") String cachedValue) {
return value;
}
@Specialization(guards = "value.equals(cachedValue)")
MyClass s8(MyClass value, @Cached("value") MyClass cachedValue) {
return value;
}
}
static class MyClass {
int equalsCalled;
@Override
public boolean equals(Object obj) {
equalsCalled++;
return super.equals(obj);
}
// override also hashCode to make javac happy
@Override
public int hashCode() {
return super.hashCode();
}
}
}