# HG changeset patch # User Christian Humer # Date 1409749133 -7200 # Node ID 1e542561783e68fbde74a5d87560102f270e8bd7 # Parent 3b3e768a2b924131976840560e7222f5c29e69f2 Truffle: new value profiles prototype. diff -r 3b3e768a2b92 -r 1e542561783e graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java Wed Sep 03 14:58:53 2014 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 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.test.utilities; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.*; +import org.junit.experimental.theories.*; +import org.junit.runner.*; + +import com.oracle.truffle.api.utilities.*; + +@RunWith(Theories.class) +public class ExactClassValueProfileTest { + + @DataPoint public static final String O1 = new String(); + @DataPoint public static final String O2 = new String(); + @DataPoint public static final Object O3 = new Object(); + @DataPoint public static final Integer O4 = new Integer(1); + @DataPoint public static final Integer O5 = null; + + private ExactClassValueProfile profile; + + @Before + public void create() { + profile = (ExactClassValueProfile) ValueProfile.createClassProfile(); + } + + @Test + public void testInitial() { + assertThat(profile.isGeneric(), is(false)); + assertThat(profile.isUninitialized(), is(true)); + assertNull(profile.getCachedClass()); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileOne(Object value) { + Object result = profile.profile(value); + + assertThat(result, is(value)); + assertEquals(profile.getCachedClass(), expectedClass(value)); + assertThat(profile.isUninitialized(), is(false)); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileTwo(Object value0, Object value1) { + Object result0 = profile.profile(value0); + Object result1 = profile.profile(value1); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + + Object expectedClass = expectedClass(value0) == expectedClass(value1) ? expectedClass(value0) : Object.class; + + assertEquals(profile.getCachedClass(), expectedClass); + assertThat(profile.isUninitialized(), is(false)); + assertThat(profile.isGeneric(), is(expectedClass == Object.class)); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileThree(Object value0, Object value1, Object value2) { + Object result0 = profile.profile(value0); + Object result1 = profile.profile(value1); + Object result2 = profile.profile(value2); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(result2, is(value2)); + + Object expectedClass = expectedClass(value0) == expectedClass(value1) && expectedClass(value1) == expectedClass(value2) ? expectedClass(value0) : Object.class; + + assertEquals(profile.getCachedClass(), expectedClass); + assertThat(profile.isUninitialized(), is(false)); + assertThat(profile.isGeneric(), is(expectedClass == Object.class)); + profile.toString(); // test that it is not crashing + } + + private static Class expectedClass(Object value) { + return value == null ? Object.class : value.getClass(); + } + +} diff -r 3b3e768a2b92 -r 1e542561783e graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java Wed Sep 03 14:58:53 2014 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, 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.test.utilities; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.*; +import org.junit.experimental.theories.*; +import org.junit.runner.*; + +import com.oracle.truffle.api.utilities.*; + +@RunWith(Theories.class) +public class IdentityValueProfileTest { + + @DataPoint public static final String O1 = new String(); + @DataPoint public static final String O2 = O1; + @DataPoint public static final Object O3 = new Object(); + @DataPoint public static final Integer O4 = new Integer(1); + @DataPoint public static final Integer O5 = null; + + private IdentityValueProfile profile; + + @Before + public void create() { + profile = (IdentityValueProfile) ValueProfile.createIdentityProfile(); + } + + @Test + public void testInitial() { + assertThat(profile.isGeneric(), is(false)); + assertThat(profile.isUninitialized(), is(true)); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileOne(Object value) { + Object result = profile.profile(value); + + assertThat(result, is(value)); + assertEquals(profile.getCachedValue(), value); + assertThat(profile.isUninitialized(), is(false)); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileTwo(Object value0, Object value1) { + Object result0 = profile.profile(value0); + Object result1 = profile.profile(value1); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + + if (value0 == value1) { + assertThat(profile.getCachedValue(), is(value0)); + assertThat(profile.isGeneric(), is(false)); + } else { + assertThat(profile.isGeneric(), is(true)); + } + assertThat(profile.isUninitialized(), is(false)); + profile.toString(); // test that it is not crashing + } + + @Theory + public void testProfileThree(Object value0, Object value1, Object value2) { + Object result0 = profile.profile(value0); + Object result1 = profile.profile(value1); + Object result2 = profile.profile(value2); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(result2, is(value2)); + + if (value0 == value1 && value1 == value2) { + assertThat(profile.getCachedValue(), is(value0)); + assertThat(profile.isGeneric(), is(false)); + } else { + assertThat(profile.isGeneric(), is(true)); + } + assertThat(profile.isUninitialized(), is(false)); + profile.toString(); // test that it is not crashing + } +} diff -r 3b3e768a2b92 -r 1e542561783e graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java Wed Sep 03 14:58:53 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, 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.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; + +/** + * Represents a {@link ValueProfile} that speculates on the exact class of a value. + */ +public final class ExactClassValueProfile extends ValueProfile { + + @CompilationFinal protected Class cachedClass; + + ExactClassValueProfile() { + } + + @SuppressWarnings("unchecked") + @Override + public T profile(T value) { + if (cachedClass != null && cachedClass.isInstance(value)) { + return (T) cachedClass.cast(value); + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (cachedClass == null && value != null) { + cachedClass = value.getClass(); + } else { + cachedClass = Object.class; + } + } + return value; + } + + public boolean isGeneric() { + return cachedClass == Object.class; + } + + public boolean isUninitialized() { + return cachedClass == null; + } + + public Class getCachedClass() { + return cachedClass; + } + + @Override + public String toString() { + return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : cachedClass.getName()), hashCode()); + } +} diff -r 3b3e768a2b92 -r 1e542561783e graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java Wed Sep 03 14:58:53 2014 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, 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.utilities; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; + +/** + * Represents a {@link ValueProfile} that speculates on the object identity of a value. + */ +public final class IdentityValueProfile extends ValueProfile { + + private static final Object UNINITIALIZED = new Object(); + private static final Object GENERIC = new Object(); + + @CompilationFinal protected Object cachedValue = UNINITIALIZED; + + IdentityValueProfile() { + } + + @Override + @SuppressWarnings("unchecked") + public T profile(T value) { + if (cachedValue != GENERIC) { + if (cachedValue == value) { + return (T) cachedValue; + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (cachedValue == UNINITIALIZED) { + cachedValue = value; + } else { + cachedValue = GENERIC; + } + } + } + return value; + } + + public boolean isGeneric() { + return getCachedValue() == GENERIC; + } + + public boolean isUninitialized() { + return getCachedValue() == UNINITIALIZED; + } + + public Object getCachedValue() { + return cachedValue; + } + + @Override + public String toString() { + return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : String.format("@%x", Objects.hash(cachedValue))), hashCode()); + } + +} diff -r 3b3e768a2b92 -r 1e542561783e graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java Wed Sep 03 14:58:53 2014 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, 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.utilities; + +/** + * Utility class to speculate on certain properties of values. + * + * Example usage: + * + *
+ * private final ValueProfile classProfile = ValueProfile.createClassProfile();
+ *
+ * return classProfile.profile(value);
+ * 
+ * + * All instances of {@code ValueProfile} (and subclasses) must be held in {@code final} fields for + * compiler optimizations to take effect. + * + * @see #createIdentityProfile() + * @see #createClassProfile() + */ +public abstract class ValueProfile { + + public abstract T profile(T value); + + /** + * Returns a {@link ValueProfile} that speculates on the exact class of a value. + */ + public static ValueProfile createClassProfile() { + return new ExactClassValueProfile(); + } + + /** + * Returns a {@link ValueProfile} that speculates on the object identity of a value. + */ + public static ValueProfile createIdentityProfile() { + return new IdentityValueProfile(); + } + +}