# HG changeset patch # User Doug Simon # Date 1383652136 -3600 # Node ID df42ff42279f2d4718802b74abfd714dbdf7cc3c # Parent 38bf986ce231c4d52da10d8c282b1dcb3a9acfc0# Parent e27f3169460e7729b5b8cc426449355832337b65 Merge. diff -r e27f3169460e -r df42ff42279f graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Nov 04 21:45:23 2013 -0800 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Nov 05 12:48:56 2013 +0100 @@ -729,8 +729,8 @@ value = unsafe.getLong(node, dataOffsets[i]); } else if (type == Boolean.TYPE) { value = unsafe.getBoolean(node, dataOffsets[i]); - } else if (type == Long.TYPE) { - value = unsafe.getLong(node, dataOffsets[i]); + } else if (type == Float.TYPE) { + value = unsafe.getFloat(node, dataOffsets[i]); } else if (type == Double.TYPE) { value = unsafe.getDouble(node, dataOffsets[i]); } else { diff -r e27f3169460e -r df42ff42279f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Nov 04 21:45:23 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Nov 05 12:48:56 2013 +0100 @@ -157,10 +157,7 @@ * Reads a word value from a given address. */ public static long unsafeReadWord(long address) { - if (getHostWordKind() == Kind.Long) { - return unsafe.getLong(address); - } - return unsafe.getInt(address); + return unsafe.getAddress(address); } /** @@ -177,7 +174,7 @@ if (getHostWordKind() == Kind.Long) { return unsafe.getLong(object, offset); } - return unsafe.getInt(object, offset); + return unsafe.getInt(object, offset) & 0xFFFFFFFFL; } protected/* final */CompilerToVM compilerToVm; diff -r e27f3169460e -r df42ff42279f graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/TestOptionValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/TestOptionValue.java Tue Nov 05 12:48:56 2013 +0100 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013, 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.graal.options.test; + +import static com.oracle.graal.options.test.TestOptionValue.Options.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.options.*; +import com.oracle.graal.options.OptionValue.OverrideScope; + +public class TestOptionValue { + + public static class Options { + public static final OptionValue Stable = new StableOptionValue<>(true); + public static final OptionValue Mutable = new OptionValue<>("original"); + public static final OptionValue SecondMutable = new OptionValue<>("second"); + } + + static final OptionDescriptor stable = new OptionDescriptor("Stable", Boolean.class, "", Options.class, "Stable", Stable); + static final OptionDescriptor mutable = new OptionDescriptor("Mutable", String.class, "", Options.class, "Mutable", Mutable); + static final OptionDescriptor secondMutable = new OptionDescriptor("SecondMutable", String.class, "", Options.class, "SecondMutable", SecondMutable); + + @Test + public void testMutable() { + assertEquals("original", Mutable.getValue()); + try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) { + assertEquals("override1", Mutable.getValue()); + try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) { + assertEquals("override2", Mutable.getValue()); + } + assertEquals("override1", Mutable.getValue()); + try (OverrideScope s3 = OptionValue.override(Mutable, "override3")) { + assertEquals("override3", Mutable.getValue()); + } + assertEquals("override1", Mutable.getValue()); + } + assertEquals("original", Mutable.getValue()); + try (OverrideScope s1 = OptionValue.override(Mutable, "original")) { + assertEquals("original", Mutable.getValue()); + } + } + + @Test + public void testMultiple() { + assertEquals("original", Mutable.getValue()); + assertEquals("second", SecondMutable.getValue()); + try (OverrideScope s1 = OptionValue.override(Mutable, "override1", SecondMutable, "secondOverride1")) { + assertEquals("override1", Mutable.getValue()); + assertEquals("secondOverride1", SecondMutable.getValue()); + try (OverrideScope s2 = OptionValue.override(Mutable, "override2", SecondMutable, "secondOverride2")) { + assertEquals("override2", Mutable.getValue()); + assertEquals("secondOverride2", SecondMutable.getValue()); + } + assertEquals("override1", Mutable.getValue()); + assertEquals("secondOverride1", SecondMutable.getValue()); + try (OverrideScope s3 = OptionValue.override(Mutable, "override3", SecondMutable, "secondOverride3")) { + assertEquals("override3", Mutable.getValue()); + assertEquals("secondOverride3", SecondMutable.getValue()); + } + assertEquals("override1", Mutable.getValue()); + assertEquals("secondOverride1", SecondMutable.getValue()); + } + assertEquals("original", Mutable.getValue()); + assertEquals("second", SecondMutable.getValue()); + try (OverrideScope s1 = OptionValue.override(Mutable, "original", SecondMutable, "second")) { + assertEquals("original", Mutable.getValue()); + assertEquals("second", SecondMutable.getValue()); + } + } + + @Test + public void testStable() { + assertTrue(Stable.getValue()); + try (OverrideScope s = OptionValue.override(Stable, false)) { + fail("cannot override stable option"); + } catch (IllegalArgumentException e) { + // expected + } + } +} diff -r e27f3169460e -r df42ff42279f graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Mon Nov 04 21:45:23 2013 -0800 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Tue Nov 05 12:48:56 2013 +0100 @@ -42,6 +42,7 @@ this.option = option; this.declaringClass = declaringClass; this.fieldName = fieldName; + option.setDescriptor(this); } /** diff -r e27f3169460e -r df42ff42279f graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Mon Nov 04 21:45:23 2013 -0800 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Tue Nov 05 12:48:56 2013 +0100 @@ -22,16 +22,120 @@ */ package com.oracle.graal.options; +import java.util.*; +import java.util.Map.Entry; + /** * An option value. */ public class OptionValue { /** + * Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of + * {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the + * object returned by this method. + *

+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be + * used: + * + *

+     * try (OverrideScope s = OptionValue.override(myOption, myValue) {
+     *     // code that depends on myOption == myValue
+     * }
+     * 
+ */ + public static OverrideScope override(OptionValue option, Object value) { + OverrideScope current = overrideScopes.get(); + if (current == null) { + if (!value.equals(option.getValue())) { + return new SingleOverrideScope(option, value); + } + Map, Object> overrides = Collections.emptyMap(); + return new MultipleOverridesScope(current, overrides); + } + return new MultipleOverridesScope(current, option, value); + } + + /** + * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue() + * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value} + * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by + * this method. + *

+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be + * used: + * + *

+     * Map overrides = new HashMap<>();
+     * overrides.put(myOption1, myValue1);
+     * overrides.put(myOption2, myValue2);
+     * try (OverrideScope s = OptionValue.override(overrides) {
+     *     // code that depends on myOption == myValue
+     * }
+     * 
+ */ + public static OverrideScope override(Map, Object> overrides) { + OverrideScope current = overrideScopes.get(); + if (current == null && overrides.size() == 1) { + Entry, Object> single = overrides.entrySet().iterator().next(); + OptionValue option = single.getKey(); + Object overrideValue = single.getValue(); + if (!overrideValue.equals(option.getValue())) { + return new SingleOverrideScope(option, overrideValue); + } + } + return new MultipleOverridesScope(current, overrides); + } + + /** + * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue() + * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value} + * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by + * this method. + *

+ * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be + * used: + * + *

+     * try (OverrideScope s = OptionValue.override(myOption1, myValue1, myOption2, myValue2) {
+     *     // code that depends on myOption == myValue
+     * }
+     * 
+ * + * @param overrides overrides in the form {@code [option1, override1, option2, override2, ...]} + */ + public static OverrideScope override(Object... overrides) { + OverrideScope current = overrideScopes.get(); + if (current == null && overrides.length == 2) { + OptionValue option = (OptionValue) overrides[0]; + Object overrideValue = overrides[1]; + if (!overrideValue.equals(option.getValue())) { + return new SingleOverrideScope(option, overrideValue); + } + } + Map, Object> map = Collections.emptyMap(); + for (int i = 0; i < overrides.length; i += 2) { + OptionValue option = (OptionValue) overrides[i]; + Object overrideValue = overrides[i + 1]; + if (!overrideValue.equals(option.getValue())) { + if (map.isEmpty()) { + map = new HashMap<>(); + } + map.put(option, overrideValue); + } + } + return new MultipleOverridesScope(current, map); + } + + private static ThreadLocal overrideScopes = new ThreadLocal<>(); + + /** * The raw option value. */ protected T value; + private OptionDescriptor descriptor; + public OptionValue(T value) { this.value = value; } @@ -55,9 +159,36 @@ } /** + * Sets the descriptor for this option. + */ + public void setDescriptor(OptionDescriptor descriptor) { + this.descriptor = descriptor; + } + + /** + * Gets the name of this option. The name for an option value with a null + * {@linkplain #setDescriptor(OptionDescriptor) descriptor} is {@code ""}. + */ + public String getName() { + return descriptor == null ? "" : (descriptor.getDeclaringClass().getName() + "." + descriptor.getName()); + } + + @Override + public String toString() { + return getName() + "=" + value; + } + + /** * Gets the value of this option. */ public T getValue() { + OverrideScope overrideScope = overrideScopes.get(); + if (overrideScope != null) { + T override = overrideScope.getOverride(this); + if (override != null) { + return override; + } + } if (value == UNINITIALIZED) { value = initialValue(); } @@ -71,4 +202,117 @@ public void setValue(Object v) { this.value = (T) v; } + + /** + * An object whose {@link #close()} method reverts the option value overriding initiated by + * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}. + */ + public abstract static class OverrideScope implements AutoCloseable { + abstract void addToInherited(Map inherited); + + abstract T getOverride(OptionValue option); + + public abstract void close(); + } + + static class SingleOverrideScope extends OverrideScope { + + private final OptionValue option; + private final Object value; + + public SingleOverrideScope(OptionValue option, Object value) { + if (option instanceof StableOptionValue) { + throw new IllegalArgumentException("Cannot override stable option " + option); + } + this.option = option; + this.value = value; + overrideScopes.set(this); + } + + @Override + void addToInherited(Map inherited) { + inherited.put(option, value); + } + + @SuppressWarnings("unchecked") + @Override + T getOverride(OptionValue key) { + if (key == this.option) { + return (T) value; + } + return null; + } + + @Override + public void close() { + overrideScopes.set(null); + } + } + + static class MultipleOverridesScope extends OverrideScope { + final OverrideScope parent; + final Map overrides; + + public MultipleOverridesScope(OverrideScope parent, OptionValue option, Object value) { + this.parent = parent; + this.overrides = new HashMap<>(); + if (parent != null) { + parent.addToInherited(overrides); + } + if (option instanceof StableOptionValue) { + throw new IllegalArgumentException("Cannot override stable option " + option); + } + if (!value.equals(option.getValue())) { + this.overrides.put(option, value); + } + if (!overrides.isEmpty()) { + overrideScopes.set(this); + } + } + + MultipleOverridesScope(OverrideScope parent, Map, Object> overrides) { + this.parent = parent; + if (overrides.isEmpty() && parent == null) { + this.overrides = Collections.emptyMap(); + return; + } + this.overrides = new HashMap<>(); + if (parent != null) { + parent.addToInherited(this.overrides); + } + for (Map.Entry, Object> e : overrides.entrySet()) { + OptionValue option = e.getKey(); + if (option instanceof StableOptionValue) { + throw new IllegalArgumentException("Cannot override stable option " + option); + } + if (!e.getValue().equals(option.getValue())) { + this.overrides.put(option, e.getValue()); + } + } + if (!this.overrides.isEmpty()) { + overrideScopes.set(this); + } + } + + @Override + void addToInherited(Map inherited) { + if (parent != null) { + parent.addToInherited(inherited); + } + inherited.putAll(overrides); + } + + @SuppressWarnings("unchecked") + @Override + T getOverride(OptionValue option) { + return (T) overrides.get(option); + } + + @Override + public void close() { + if (!overrides.isEmpty()) { + overrideScopes.set(parent); + } + } + } } diff -r e27f3169460e -r df42ff42279f mx/projects --- a/mx/projects Mon Nov 04 21:45:23 2013 -0800 +++ b/mx/projects Tue Nov 05 12:48:56 2013 +0100 @@ -200,6 +200,14 @@ project@com.oracle.graal.options@annotationProcessorForDependents=true project@com.oracle.graal.options@workingSets=Graal,Codegen +# graal.options.test +project@com.oracle.graal.options.test@subDir=graal +project@com.oracle.graal.options.test@sourceDirs=src +project@com.oracle.graal.options.test@dependencies=com.oracle.graal.options,JUNIT +project@com.oracle.graal.options.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.options.test@javaCompliance=1.7 +project@com.oracle.graal.options.test@workingSets=Graal + # graal.graph project@com.oracle.graal.graph@subDir=graal project@com.oracle.graal.graph@sourceDirs=src