/*
* 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 org.junit.Test;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
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.test.TypeBoxingTestFactory.TypeBoxingTest1NodeGen;
import com.oracle.truffle.api.dsl.test.TypeBoxingTestFactory.TypeBoxingTest2NodeGen;
import com.oracle.truffle.api.dsl.test.TypeBoxingTestFactory.TypeBoxingTest3NodeGen;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
public class TypeBoxingTest {
@Test
public void testTypeBoxing11() {
ConstantNode constantNode = new ConstantNode();
TypeBoxingTest1 test = TypeBoxingTest1NodeGen.create(constantNode);
test.execute();
assertEquals(1, constantNode.executeInvoked);
assertEquals(0, constantNode.executeIntInvoked);
test.execute();
assertEquals(1, constantNode.executeInvoked);
assertEquals(1, constantNode.executeIntInvoked);
}
@Test
public void testTypeBoxing12() throws UnexpectedResultException {
ConstantNode constantNode = new ConstantNode();
TypeBoxingTest1 test = TypeBoxingTest1NodeGen.create(constantNode);
test.executeInt();
assertEquals(0, constantNode.executeInvoked);
assertEquals(1, constantNode.executeIntInvoked);
test.executeInt();
assertEquals(0, constantNode.executeInvoked);
assertEquals(2, constantNode.executeIntInvoked);
}
@NodeChild
abstract static class TypeBoxingTest1 extends TestNode {
@Specialization
protected int doInt(int value) {
return value;
}
@Specialization
protected Object doInt(Object value) {
return value;
}
}
@Test
public void testTypeBoxing21() {
ConstantNode constantNode = new ConstantNode();
TypeBoxingTest2 test = TypeBoxingTest2NodeGen.create(constantNode);
test.execute();
assertEquals(1, constantNode.executeInvoked);
assertEquals(0, constantNode.executeIntInvoked);
test.execute();
assertEquals(1, constantNode.executeInvoked);
assertEquals(1, constantNode.executeIntInvoked);
}
@Test
public void testTypeBxoing22() throws UnexpectedResultException {
ConstantNode constantNode = new ConstantNode();
TypeBoxingTest2 test = TypeBoxingTest2NodeGen.create(constantNode);
test.executeInt();
assertEquals(1, constantNode.executeInvoked);
assertEquals(0, constantNode.executeIntInvoked);
test.executeInt();
assertEquals(1, constantNode.executeInvoked);
assertEquals(1, constantNode.executeIntInvoked);
}
@NodeChild
abstract static class TypeBoxingTest2 extends TestNode {
@Specialization
protected int doInt(int value) {
return value;
}
@Specialization
protected int doInt(Object value) {
return (int) value;
}
}
@Test
public void testTypeBoxing31() throws UnexpectedResultException {
ConstantNode arg1 = new ConstantNode();
ConstantNode arg2 = new ConstantNode();
TypeBoxingTest3 test = TypeBoxingTest3NodeGen.create(arg1, arg2);
arg1.value = 1;
arg2.value = 1;
// first time we don't know the types we need to execute
test.executeInt();
assertEquals(1, arg1.executeInvoked);
assertEquals(0, arg1.executeIntInvoked);
assertEquals(1, arg2.executeInvoked);
assertEquals(0, arg2.executeIntInvoked);
// next time int,int is active both children must be executed
// with executeInt
test.executeInt();
assertEquals(1, arg1.executeInvoked);
assertEquals(1, arg1.executeIntInvoked);
assertEquals(1, arg2.executeInvoked);
assertEquals(1, arg2.executeIntInvoked);
arg1.value = -1;
arg2.value = 1;
// now int, Object should become active, but the node
// still believes it is in int,int so executeInt is executed
// for both children
test.executeInt();
assertEquals(1, arg1.executeInvoked);
assertEquals(2, arg1.executeIntInvoked);
assertEquals(1, arg2.executeInvoked);
assertEquals(2, arg2.executeIntInvoked);
// now we are rewritten to int,Object and the node needs
// to execute the second child with Object.
test.executeInt();
assertEquals(1, arg1.executeInvoked);
assertEquals(3, arg1.executeIntInvoked);
assertEquals(2, arg2.executeInvoked);
assertEquals(2, arg2.executeIntInvoked);
arg1.value = 1;
arg2.value = -1;
// now Object, int should become activate the node
// still believes iut is in int, Object so executeInt is
// executed for the first argument.
test.executeInt();
assertEquals(1, arg1.executeInvoked);
assertEquals(4, arg1.executeIntInvoked);
assertEquals(3, arg2.executeInvoked);
assertEquals(2, arg2.executeIntInvoked);
test.executeInt();
assertEquals(2, arg1.executeInvoked);
assertEquals(4, arg1.executeIntInvoked);
assertEquals(4, arg2.executeInvoked);
assertEquals(2, arg2.executeIntInvoked);
}
@NodeChildren({@NodeChild, @NodeChild})
abstract static class TypeBoxingTest3 extends TestNode {
@Specialization(guards = "value1 < 0")
protected Object doInt(int value1, Object value2) {
return value1 + (int) value2;
}
@Specialization(guards = "value2 < 0")
protected Object doInt(Object value1, int value2) {
return (int) value1 + value2;
}
@Specialization(guards = {"value1 >= 0", "value2 >= 0"})
protected Object doInt(int value1, int value2) {
return value1 + value2;
}
}
@TypeSystemReference(TypeBoxingTypeSystem.class)
abstract static class TestNode extends Node {
public abstract Object execute();
public abstract int executeInt() throws UnexpectedResultException;
}
static class ConstantNode extends TestNode {
int executeInvoked;
int executeIntInvoked;
int value = 1;
@Override
public Object execute() {
executeInvoked++;
return value;
}
@Override
public int executeInt() throws UnexpectedResultException {
executeIntInvoked++;
return value;
}
}
@TypeSystem
static class TypeBoxingTypeSystem {
}
}