changeset 21180:c2f5dc4418d0

Merge
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Sat, 02 May 2015 14:40:49 -0700
parents fab864299d96 f1f7695b5bdc
children 78a4b44420cf
files
diffstat 18 files changed, 479 insertions(+), 268 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Sat May 02 14:36:00 2015 -0700
+++ b/CHANGELOG.md	Sat May 02 14:40:49 2015 -0700
@@ -4,15 +4,18 @@
 
 
 ## `tip`
+...
+
+## Version 0.7
+29-Apr-2015, [Repository Revision](http://hg.openjdk.java.net/graal/graal/shortlog/graal-0.7)
 ### Graal
 * By default the Graal code is now only compiled by C1 which should improve application start-up.
 * Merged with jdk8u40-b25.
 * The Graal class loader now loads all lib/graal/graal*.jar jars.
-* Fast Graal services (see com.oracle.graal.api.runtime.Service) are now looked up using service files in lib/graal/services
+* Fast Graal services (see com.oracle.graal.api.runtime.Service) are now looked up using service files in lib/graal/services.
 * Add utilities ModifiersProvider#isConcrete, ResolvedJavaMethod#hasBytecodes, ResolvedJavaMethod#hasReceiver to Graal API.
 * Add `GraalDirectives` API, containing methods to influence compiler behavior for unittests and microbenchmarks.
 * Introduce `LIRSuites`, an extensible configuration for the low-level compiler pipeline.
-* ...
 
 ### Truffle
 * New, faster partial evaluation (no more TruffleCache).
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java	Sat May 02 14:40:49 2015 -0700
@@ -205,7 +205,8 @@
                 } else {
                     joinType = null;
                 }
-                if (joinExactType || (!type.isInterface() && !other.type.isInterface())) {
+
+                if (joinExactType || (!isInterfaceOrArrayOfInterface(type) && !isInterfaceOrArrayOfInterface(other.type))) {
                     joinAlwaysNull = true;
                 }
             }
@@ -231,6 +232,10 @@
         }
     }
 
+    private static boolean isInterfaceOrArrayOfInterface(ResolvedJavaType t) {
+        return t.isInterface() || (t.isArray() && t.getElementalType().isInterface());
+    }
+
     public static boolean isConcreteType(ResolvedJavaType type) {
         return !(type.isAbstract() && !type.isArray());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GuardEliminationCornerCasesTest.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GuardEliminationCornerCasesTest.java	Sat May 02 14:40:49 2015 -0700
@@ -62,11 +62,11 @@
                     if (b instanceof C) {
                         return 1;
                     } else {
-                        GraalDirectives.deoptimize();
+                        GraalDirectives.deoptimizeAndInvalidate();
                     }
                 }
             } else {
-                GraalDirectives.deoptimize();
+                GraalDirectives.deoptimizeAndInvalidate();
             }
         }
         return 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast03.java	Sat May 02 14:40:49 2015 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 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.jtt.bytecode;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+/**
+ * Tests the checkcast works, when casting an array of interface.
+ */
+public class BC_checkcast03 extends JTTTest {
+
+    public interface IObject {
+
+    }
+
+    private static class BaseClass {
+
+    }
+
+    private static class TestClass extends BaseClass implements IObject {
+    }
+
+    static TestClass[] a1 = {new TestClass()};
+
+    public static BaseClass[] getBaseClassArray() {
+        return a1;
+    }
+
+    public static IObject[] test() {
+        return (IObject[]) getBaseClassArray();
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test");
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Sat May 02 14:40:49 2015 -0700
@@ -78,7 +78,7 @@
             }
         }
         if (!isStatic() && forObject.isNullConstant()) {
-            return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
+            return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
         }
         return this;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Sat May 02 14:40:49 2015 -0700
@@ -134,6 +134,9 @@
     }
 
     private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
+        if (!deoptAction.doesInvalidateCompilation()) {
+            return;
+        }
         if (deoptBegin instanceof AbstractMergeNode) {
             AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
             Debug.log("Visiting %s", mergeNode);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Sat May 02 14:40:49 2015 -0700
@@ -40,7 +40,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.LoweringPhase.*;
+import com.oracle.graal.phases.common.LoweringPhase.Frame;
 import com.oracle.graal.phases.schedule.*;
 
 public class DominatorConditionalEliminationPhase extends Phase {
@@ -54,8 +54,8 @@
     }
 
     private static final class InfoElement {
-        private Stamp stamp;
-        private ValueNode guard;
+        private final Stamp stamp;
+        private final ValueNode guard;
 
         public InfoElement(Stamp stamp, ValueNode guard) {
             this.stamp = stamp;
@@ -69,10 +69,15 @@
         public ValueNode getGuard() {
             return guard;
         }
+
+        @Override
+        public String toString() {
+            return stamp + " -> " + guard;
+        }
     }
 
     private static final class Info {
-        private ArrayList<InfoElement> infos;
+        private final ArrayList<InfoElement> infos;
 
         public Info() {
             infos = new ArrayList<>();
@@ -267,7 +272,7 @@
         }
 
         private void registerCondition(LogicNode condition, boolean negated, ValueNode guard, List<Runnable> undoOperations) {
-            this.registerNewStamp(condition, negated ? StampFactory.contradiction() : StampFactory.tautology(), guard, undoOperations);
+            registerNewStamp(condition, negated ? StampFactory.contradiction() : StampFactory.tautology(), guard, undoOperations);
         }
 
         private Iterable<InfoElement> getInfoElements(ValueNode proxiedValue) {
@@ -368,11 +373,11 @@
                 if (this.loopExits.isEmpty()) {
                     return tryProofCondition(shortCircuitOrNode.getX(), (guard, result) -> {
                         if (result == !shortCircuitOrNode.isXNegated()) {
-                            return rewireGuards(guard, result, rewireGuardFunction);
+                            return rewireGuards(guard, true, rewireGuardFunction);
                         } else {
                             return tryProofCondition(shortCircuitOrNode.getY(), (innerGuard, innerResult) -> {
                                 if (innerGuard == guard) {
-                                    return rewireGuards(guard, shortCircuitOrNode.isYNegated() ? !innerResult : innerResult, rewireGuardFunction);
+                                    return rewireGuards(guard, innerResult ^ shortCircuitOrNode.isYNegated(), rewireGuardFunction);
                                 }
                                 return false;
                             });
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithBoxing.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithBoxing.java	Sat May 02 14:40:49 2015 -0700
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.truffle;
 
-import java.lang.reflect.*;
 import java.util.*;
 
-import sun.misc.*;
-
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
@@ -236,70 +233,4 @@
     static <T> T unsafeCast(Object value, Class<T> type, boolean condition, boolean nonNull) {
         return (T) value;
     }
-
-    @SuppressWarnings("unused")
-    static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return UNSAFE.getInt(receiver, offset);
-    }
-
-    @SuppressWarnings("unused")
-    static long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return UNSAFE.getLong(receiver, offset);
-    }
-
-    @SuppressWarnings("unused")
-    static float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return UNSAFE.getFloat(receiver, offset);
-    }
-
-    @SuppressWarnings("unused")
-    static double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return UNSAFE.getDouble(receiver, offset);
-    }
-
-    @SuppressWarnings("unused")
-    static Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
-        return UNSAFE.getObject(receiver, offset);
-    }
-
-    @SuppressWarnings("unused")
-    static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) {
-        UNSAFE.putInt(receiver, offset, value);
-    }
-
-    @SuppressWarnings("unused")
-    static void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity) {
-        UNSAFE.putLong(receiver, offset, value);
-    }
-
-    @SuppressWarnings("unused")
-    static void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity) {
-        UNSAFE.putFloat(receiver, offset, value);
-    }
-
-    @SuppressWarnings("unused")
-    static void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity) {
-        UNSAFE.putDouble(receiver, offset, value);
-    }
-
-    @SuppressWarnings("unused")
-    static void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity) {
-        UNSAFE.putObject(receiver, offset, value);
-    }
-
-    private static final Unsafe UNSAFE = getUnsafe();
-
-    private static Unsafe getUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Sat May 02 14:40:49 2015 -0700
@@ -104,7 +104,8 @@
     }
 
     private Object getObjectUnsafe(int slotIndex, FrameSlot slot) {
-        return unsafeGetObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, this.getTags()[slotIndex] == FrameSlotKind.Object.tag, slot);
+        boolean condition = this.getTags()[slotIndex] == OBJECT_TAG;
+        return unsafeGetObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, condition, slot);
     }
 
     @Override
@@ -127,7 +128,7 @@
 
     private byte getByteUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Byte.tag;
+        boolean condition = this.getTags()[slotIndex] == BYTE_TAG;
         return (byte) unsafeGetInt(getPrimitiveLocals(), offset, condition, slot);
     }
 
@@ -152,7 +153,7 @@
 
     private boolean getBooleanUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Boolean.tag;
+        boolean condition = this.getTags()[slotIndex] == BOOLEAN_TAG;
         return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot) != 0;
     }
 
@@ -177,7 +178,7 @@
 
     private float getFloatUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Float.tag;
+        boolean condition = this.getTags()[slotIndex] == FLOAT_TAG;
         return unsafeGetFloat(getPrimitiveLocals(), offset, condition, slot);
     }
 
@@ -202,7 +203,7 @@
 
     private long getLongUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Long.tag;
+        boolean condition = this.getTags()[slotIndex] == LONG_TAG;
         return unsafeGetLong(getPrimitiveLocals(), offset, condition, slot);
     }
 
@@ -227,7 +228,7 @@
 
     private int getIntUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Int.tag;
+        boolean condition = this.getTags()[slot.getIndex()] == INT_TAG;
         return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot);
     }
 
@@ -252,7 +253,7 @@
 
     private double getDoubleUnsafe(int slotIndex, FrameSlot slot) {
         long offset = getPrimitiveOffset(slotIndex);
-        boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Double.tag;
+        boolean condition = this.getTags()[slotIndex] == DOUBLE_TAG;
         return unsafeGetDouble(getPrimitiveLocals(), offset, condition, slot);
     }
 
@@ -306,20 +307,20 @@
             resize();
         }
         byte tag = getTags()[slotIndex];
-        if (tag == FrameSlotKind.Boolean.tag) {
+        if (tag == BOOLEAN_TAG) {
             return getBooleanUnsafe(slotIndex, slot);
-        } else if (tag == FrameSlotKind.Byte.tag) {
+        } else if (tag == BYTE_TAG) {
             return getByteUnsafe(slotIndex, slot);
-        } else if (tag == FrameSlotKind.Int.tag) {
+        } else if (tag == INT_TAG) {
             return getIntUnsafe(slotIndex, slot);
-        } else if (tag == FrameSlotKind.Double.tag) {
+        } else if (tag == DOUBLE_TAG) {
             return getDoubleUnsafe(slotIndex, slot);
-        } else if (tag == FrameSlotKind.Long.tag) {
+        } else if (tag == LONG_TAG) {
             return getLongUnsafe(slotIndex, slot);
-        } else if (tag == FrameSlotKind.Float.tag) {
+        } else if (tag == FLOAT_TAG) {
             return getFloatUnsafe(slotIndex, slot);
         } else {
-            assert tag == FrameSlotKind.Object.tag;
+            assert tag == OBJECT_TAG;
             return getObjectUnsafe(slotIndex, slot);
         }
     }
@@ -348,37 +349,37 @@
 
     @Override
     public boolean isObject(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Object.tag;
+        return getTag(slot) == OBJECT_TAG;
     }
 
     @Override
     public boolean isByte(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Byte.tag;
+        return getTag(slot) == BYTE_TAG;
     }
 
     @Override
     public boolean isBoolean(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Boolean.tag;
+        return getTag(slot) == BOOLEAN_TAG;
     }
 
     @Override
     public boolean isInt(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Int.tag;
+        return getTag(slot) == INT_TAG;
     }
 
     @Override
     public boolean isLong(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Long.tag;
+        return getTag(slot) == LONG_TAG;
     }
 
     @Override
     public boolean isFloat(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Float.tag;
+        return getTag(slot) == FLOAT_TAG;
     }
 
     @Override
     public boolean isDouble(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Double.tag;
+        return getTag(slot) == DOUBLE_TAG;
     }
 
     @SuppressWarnings({"unchecked", "unused"})
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Sat May 02 14:40:49 2015 -0700
@@ -167,8 +167,7 @@
 
     /**
      * Materializes this frame, which allows it to be stored in a field or cast to
-     * {@link java.lang.Object}. The frame however looses the ability to be packed or to access the
-     * caller frame.
+     * {@link java.lang.Object}.
      *
      * @return the new materialized frame
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Sat May 02 14:40:49 2015 -0700
@@ -27,9 +27,7 @@
 /**
  * Represents a materialized frame containing values of local variables of the guest language. It
  * can be created using the {@link VirtualFrame#materialize()} method. Instances of this type are
- * the only frame instances that may be stored in fields or cast to {@link java.lang.Object}. In
- * contrast to a {@link VirtualFrame}, a {@link MaterializedFrame} can no longer be packed and it
- * also does not provide access to the caller frame.
+ * the only frame instances that may be stored in fields or cast to {@link java.lang.Object}.
  */
 public interface MaterializedFrame extends Frame {
 
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/ForeignAccessArguments.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/ForeignAccessArguments.java	Sat May 02 14:40:49 2015 -0700
@@ -54,6 +54,10 @@
         return copyOfRange(arguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
     }
 
+    public static Object[] extractUserArguments(int skip, Object[] arguments) {
+        return copyOfRange(arguments, RUNTIME_ARGUMENT_COUNT + skip, arguments.length);
+    }
+
     public static int getUserArgumentCount(Object[] arguments) {
         return arguments.length - RUNTIME_ARGUMENT_COUNT;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleGlobalScope.java	Sat May 02 14:40:49 2015 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 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.interop;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.interop.*;
+
+public interface TruffleGlobalScope {
+    void exportTruffleObject(Object identifier, TruffleObject object);
+
+    FrameSlot getFrameSlot(Object identifier);
+
+    TruffleObject getTruffleObject(FrameSlot slot);
+
+    boolean contains(Object identifier);
+}
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleLanguage.java	Sat May 02 14:36:00 2015 -0700
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/TruffleLanguage.java	Sat May 02 14:40:49 2015 -0700
@@ -29,12 +29,12 @@
 public interface TruffleLanguage {
     String getLanguageName();
 
-    TruffleObject getLanguageContext();
-
-    void setGlobalContext(TruffleObject context);
-
-    boolean hasGlobalProperty(String name);
-
     Object run(String[] arguments);
 
+    void setTruffleGlobalScope(TruffleGlobalScope globalScope);
+
+    TruffleObject getLanguageGlobal();
+
+    boolean isObjectOfLanguage(TruffleObject object);
+
 }
--- a/mx/mx_graal.py	Sat May 02 14:36:00 2015 -0700
+++ b/mx/mx_graal.py	Sat May 02 14:40:49 2015 -0700
@@ -118,7 +118,7 @@
         return _vm
     vm = mx.get_env('DEFAULT_VM')
     if vm is None:
-        if not sys.stdout.isatty():
+        if not mx.is_interactive():
             mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable')
         envPath = join(_graal_home, 'mx', 'env')
         mx.log('Please select the VM to be executed from the following: ')
@@ -392,7 +392,7 @@
     if not vm:
         vm = _get_vm()
     mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
-    if sys.stdout.isatty():
+    if mx.is_interactive():
         if mx.ask_yes_no('Build it now', 'y'):
             with VM(vm, bld):
                 build([])
@@ -1714,9 +1714,8 @@
 
     with Task('CleanAndBuildIdealGraphVisualizer', tasks) as t:
         if t and platform.processor() != 'sparc':
-            env = _igvFallbackJDK(os.environ)
             buildxml = mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'))
-            mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=env)
+            mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv())
 
     # Prevent Graal modifications from breaking the standard builds
     if args.buildNonGraal:
@@ -1758,6 +1757,11 @@
     if args.task_filter:
         Task.filters = args.task_filter.split(',')
 
+    # Force
+    if not mx._opts.strict_compliance:
+        mx.log("[gate] foring strict compliance")
+        mx._opts.strict_compliance = True
+
     tasks = []
     total = Task('Gate')
     try:
@@ -1861,38 +1865,34 @@
 
     dacapo(['100', 'eclipse', '-esa'])
 
-def _igvFallbackJDK(env):
+def _igvJdk():
     v8u20 = mx.VersionSpec("1.8.0_20")
     v8u40 = mx.VersionSpec("1.8.0_40")
     v8 = mx.VersionSpec("1.8")
-    igvHomes = [h for h in mx._java_homes if h.version >= v8 and (h.version < v8u20 or h.version >= v8u40)]
-    defaultJava = mx.java()
-    if defaultJava not in igvHomes:
-        if not igvHomes:
-            mx.abort("No JDK available for building IGV. Must have JDK >= 1.8 and < 1.8.0u20 or >= 1.8.0u40 in JAVA_HOME or EXTRA_JAVA_HOMES")
-        env = dict(env)
-        fallbackJDK = igvHomes[0]
-        mx.logv("1.8.0_20 has a known javac bug (JDK-8043926), thus falling back to " + str(fallbackJDK.version))
-        env['JAVA_HOME'] = str(fallbackJDK.jdk)
+    def _igvJdkVersionCheck(version):
+        return version >= v8 and (version < v8u20 or version >= v8u40)
+    return mx.java_version(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40').jdk
+
+def _igvBuildEnv():
+        # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs
+    env = dict(os.environ)
+    proxy = os.environ.get('http_proxy')
+    if not (proxy is None) and len(proxy) > 0:
+        if '://' in proxy:
+            # Remove the http:// prefix (or any other protocol prefix)
+            proxy = proxy.split('://', 1)[1]
+        # Separate proxy server name and port number
+        proxyName, proxyPort = proxy.split(':', 1)
+        proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort
+        env['ANT_OPTS'] = proxyEnv
+
+    env['JAVA_HOME'] = _igvJdk()
     return env
 
 def igv(args):
     """run the Ideal Graph Visualizer"""
     logFile = '.ideal_graph_visualizer.log'
     with open(join(_graal_home, logFile), 'w') as fp:
-        # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs
-        env = dict(os.environ)
-        proxy = os.environ.get('http_proxy')
-        if not (proxy is None) and len(proxy) > 0:
-            if '://' in proxy:
-                # Remove the http:// prefix (or any other protocol prefix)
-                proxy = proxy.split('://', 1)[1]
-            # Separate proxy server name and port number
-            proxyName, proxyPort = proxy.split(':', 1)
-            proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort
-            env['ANT_OPTS'] = proxyEnv
-        env = _igvFallbackJDK(env)
-
         mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']')
         nbplatform = join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')
 
@@ -1914,6 +1914,8 @@
 
         if not exists(nbplatform):
             mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]')
+
+        env = _igvBuildEnv()
         # make the jar for Batik 1.7 available.
         env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True)
         if mx.run(['ant', '-f', mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False):
@@ -2571,7 +2573,7 @@
     findbugsResults = join(_graal_home, 'findbugs.results')
 
     cmd = ['-jar', mx._cygpathU2W(findbugsJar), '-textui', '-low', '-maxRank', '15']
-    if sys.stdout.isatty():
+    if mx.is_interactive():
         cmd.append('-progress')
     cmd = cmd + ['-auxclasspath', mx._separatedCygpathU2W(mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects])), '-output', mx._cygpathU2W(findbugsResults), '-exitcode'] + args + outputDirs
     exitcode = mx.run_java(cmd, nonZeroIsFatal=False, javaConfig=mx.java(javaCompliance))
--- a/mxtool/.pylintrc	Sat May 02 14:36:00 2015 -0700
+++ b/mxtool/.pylintrc	Sat May 02 14:40:49 2015 -0700
@@ -44,7 +44,8 @@
         too-many-lines,missing-docstring,no-init,no-self-use,too-many-statements,
         too-many-locals,too-few-public-methods,too-many-instance-attributes,
         too-many-arguments,too-many-branches,too-many-public-methods,
-        multiple-statements,abstract-method,F0401,no-member,non-parent-init-called
+        multiple-statements,abstract-method,F0401,no-member,non-parent-init-called,
+        maybe-no-member
 
 # F0401: http://www.logilab.org/ticket/9386
 
--- a/mxtool/mx.py	Sat May 02 14:36:00 2015 -0700
+++ b/mxtool/mx.py	Sat May 02 14:40:49 2015 -0700
@@ -47,6 +47,11 @@
 from argparse import ArgumentParser, REMAINDER
 from os.path import join, basename, dirname, exists, getmtime, isabs, expandvars, isdir, isfile
 
+# needed to work around https://bugs.python.org/issue1927
+import readline
+#then make pylint happy..
+readline.get_line_buffer()
+
 # Support for Python 2.6
 def check_output(*popenargs, **kwargs):
     process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
@@ -94,7 +99,8 @@
 _primary_suite_path = None
 _primary_suite = None
 _opts = None
-_java_homes = None
+_extra_java_homes = []
+_default_java_home = None
 _warn = False
 
 """
@@ -213,10 +219,6 @@
                             if p.javaCompliance > self.javaCompliance:
                                 abort("Compliance level doesn't match: Distribution {0} requires {1}, but {2} is {3}.".format(self.name, self.javaCompliance, p.name, p.javaCompliance))
 
-                        # skip a  Java project if its Java compliance level is "higher" than the configured JDK
-                        jdk = java(p.javaCompliance)
-                        assert jdk
-
                         logv('[' + self.path + ': adding project ' + p.name + ']')
                         outputDir = p.output_dir()
                         for root, _, files in os.walk(outputDir):
@@ -306,14 +308,6 @@
         self.definedAnnotationProcessors = None
         self.definedAnnotationProcessorsDist = None
 
-
-        # Verify that a JDK exists for this project if its compliance level is
-        # less than the compliance level of the default JDK
-        jdk = java(self.javaCompliance)
-        if jdk is None and self.javaCompliance < java().javaCompliance:
-            abort('Cannot find ' + str(self.javaCompliance) + ' JDK required by ' + name + '. ' +
-                  'Specify it with --extra-java-homes option or EXTRA_JAVA_HOMES environment variable.')
-
         # Create directories for projects that don't yet exist
         if not exists(d):
             os.mkdir(d)
@@ -755,6 +749,7 @@
         sha1path = path + '.sha1'
 
         includedInJDK = getattr(self, 'includedInJDK', None)
+        # TODO since we don't know which JDK will be used, this check is dubious
         if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK):
             return None
 
@@ -1230,7 +1225,7 @@
                         del _libs[d.name]
                         self.libs.remove(d)
             elif d.isProject():
-                if java(d.javaCompliance) is None:
+                if java(d.javaCompliance, cancel='some projects will be omitted which may result in errrors') is None:
                     logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance))
                     del _projects[d.name]
                     self.projects.remove(d)
@@ -1656,68 +1651,6 @@
         p.all_deps(deps, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors)
     return deps
 
-def _handle_lookup_java_home(jdk):
-    return _handle_lookup_jdk(jdk, 'JAVA_HOME', '--java-home', False)
-
-def _handle_lookup_extra_java_homes(jdk):
-    return _handle_lookup_jdk(jdk, 'EXTRA_JAVA_HOMES', '--extra-java-homes', True)
-
-def _handle_lookup_jdk(jdk, varName, flagName, allowMultiple):
-    if jdk != None and jdk != '':
-        return jdk
-    jdk = os.environ.get(varName)
-    if jdk != None and jdk != '':
-        return jdk
-
-    if not sys.stdout.isatty():
-        abort('Could not find bootstrap {0}. Use {1} option or ensure {2} environment variable is set.'.format(varName, flagName, varName))
-
-    candidateJdks = []
-    if get_os() == 'darwin':
-        base = '/Library/Java/JavaVirtualMachines'
-        if exists(base):
-            candidateJdks = [join(base, n, 'Contents/Home') for n in os.listdir(base) if exists(join(base, n, 'Contents/Home'))]
-    elif get_os() == 'linux':
-        base = '/usr/lib/jvm'
-        if exists(base):
-            candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
-        base = '/usr/java'
-        if exists(base):
-            candidateJdks += [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
-    elif get_os() == 'solaris':
-        base = '/usr/jdk/instances'
-        if exists(base):
-            candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, 'jre/lib/rt.jar'))]
-    elif get_os() == 'windows':
-        base = r'C:\Program Files\Java'
-        if exists(base):
-            candidateJdks = [join(base, n) for n in os.listdir(base) if exists(join(base, n, r'jre\lib\rt.jar'))]
-
-    javaHome = None
-    if len(candidateJdks) != 0:
-        log('Missing value for {0}.'.format(varName))
-        javaHome = select_items(candidateJdks + ['<other>'], allowMultiple=allowMultiple)
-        if javaHome == '<other>':
-            javaHome = None
-        if javaHome != None and allowMultiple:
-            javaHome = os.pathsep.join(javaHome)
-
-    while javaHome is None:
-        javaHome = raw_input('Enter path of JDK for {0}: '.format(varName))
-        rtJarPath = join(javaHome, 'jre', 'lib', 'rt.jar')
-        if not exists(rtJarPath):
-            log('Does not appear to be a valid JDK as ' + rtJarPath + ' does not exist')
-            javaHome = None
-        else:
-            break
-
-    envPath = join(_primary_suite.mxDir, 'env')
-    if ask_yes_no('Persist this setting by adding "{0}={1}" to {2}'.format(varName, javaHome, envPath), 'y'):
-        with open(envPath, 'a') as fp:
-            print >> fp, varName + '=' + javaHome
-
-    return javaHome
-
 class ArgParser(ArgumentParser):
     # Override parent to append the list of available commands
     def format_help(self):
@@ -1744,6 +1677,7 @@
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
         self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='<path>')
         self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='<path>')
+        self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects of a certain compliance will only be built with a JDK of this exact compliance', default=False)
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
         self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes')
         if get_os() != 'windows':
@@ -1769,15 +1703,16 @@
         if opts.very_verbose:
             opts.verbose = True
 
-        opts.java_home = _handle_lookup_java_home(opts.java_home)
-        opts.extra_java_homes = _handle_lookup_extra_java_homes(opts.extra_java_homes)
-
         if opts.user_home is None or opts.user_home == '':
             abort('Could not find user home. Use --user-home option or ensure HOME environment variable is set.')
 
-        os.environ['JAVA_HOME'] = opts.java_home
+        if opts.java_home:
+            os.environ['JAVA_HOME'] = opts.java_home
         os.environ['HOME'] = opts.user_home
 
+        if os.environ.get('STRICT_COMPLIANCE'):
+            _opts.strict_compliance = True
+
         opts.ignored_projects = opts.ignored_projects + os.environ.get('IGNORED_PROJECTS', '').split(',')
 
         commandAndArgs = opts.__dict__.pop('commandAndArgs')
@@ -1796,19 +1731,231 @@
         msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0])
     return msg + '\n'
 
-def java(requiredCompliance=None):
+_canceled_java_requests = set()
+
+def java(requiredCompliance=None, purpose=None, cancel=None):
     """
     Get a JavaConfig object containing Java commands launch details.
     If requiredCompliance is None, the compliance level specified by --java-home/JAVA_HOME
     is returned. Otherwise, the JavaConfig exactly matching requiredCompliance is returned
     or None if there is no exact match.
     """
-    assert _java_homes
+
+    global _default_java_home
+    if cancel and (requiredCompliance, purpose) in _canceled_java_requests:
+        return None
+
     if not requiredCompliance:
-        return _java_homes[0]
-    for java in _java_homes:
-        if java.javaCompliance == requiredCompliance:
+        if not _default_java_home:
+            _default_java_home = _find_jdk(purpose=purpose, cancel=cancel)
+            if not _default_java_home:
+                assert cancel
+                _canceled_java_requests.add((requiredCompliance, purpose))
+        return _default_java_home
+
+    if _opts.strict_compliance:
+        complianceCheck = requiredCompliance.exactMatch
+        desc = str(requiredCompliance)
+    else:
+        compVersion = VersionSpec(str(requiredCompliance))
+        complianceCheck = lambda version: version >= compVersion
+        desc = '>=' + str(requiredCompliance)
+
+    for java in _extra_java_homes:
+        if complianceCheck(java.version):
             return java
+
+    jdk = _find_jdk(versionCheck=complianceCheck, versionDescription=desc, purpose=purpose, cancel=cancel)
+    if jdk:
+        assert jdk not in _extra_java_homes
+        _extra_java_homes.append(jdk)
+    else:
+        assert cancel
+        _canceled_java_requests.add((requiredCompliance, purpose))
+    return jdk
+
+def java_version(versionCheck, versionDescription=None, purpose=None):
+    if _default_java_home and versionCheck(_default_java_home.version):
+        return _default_java_home
+    for java in _extra_java_homes:
+        if versionCheck(java.version):
+            return java
+    jdk = _find_jdk(versionCheck, versionDescription, purpose)
+    assert jdk not in _extra_java_homes
+    _extra_java_homes.append(jdk)
+    return jdk
+
+def _find_jdk(versionCheck=None, versionDescription=None, purpose=None, cancel=None):
+    if not versionCheck:
+        versionCheck = lambda v: True
+    assert not versionDescription or versionCheck
+    if not versionCheck and not purpose:
+        isDefaultJdk = True
+    else:
+        isDefaultJdk = False
+
+    candidateJdks = []
+    source = ''
+    if _opts.java_home:
+        candidateJdks.append(_opts.java_home)
+        source = '--java-home'
+    elif os.environ.get('JAVA_HOME'):
+        candidateJdks.append(os.environ.get('JAVA_HOME'))
+        source = 'JAVA_HOME'
+
+    result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source)
+    if result:
+        return result
+
+    candidateJdks = []
+
+    if _opts.extra_java_homes:
+        candidateJdks += _opts.extra_java_homes.split(os.pathsep)
+        source = '--extra-java-homes'
+    elif os.environ.get('EXTRA_JAVA_HOMES'):
+        candidateJdks += os.environ.get('EXTRA_JAVA_HOMES').split(os.pathsep)
+        source = 'EXTRA_JAVA_HOMES'
+
+    result = _find_jdk_in_candidates(candidateJdks, versionCheck, warn=True, source=source)
+    if not result:
+        candidateJdks = []
+        source = ''
+
+        if get_os() == 'darwin':
+            base = '/Library/Java/JavaVirtualMachines'
+            if exists(base):
+                candidateJdks = [join(base, n, 'Contents/Home') for n in os.listdir(base)]
+        elif get_os() == 'linux':
+            base = '/usr/lib/jvm'
+            if exists(base):
+                candidateJdks = [join(base, n) for n in os.listdir(base)]
+            base = '/usr/java'
+            if exists(base):
+                candidateJdks += [join(base, n) for n in os.listdir(base)]
+        elif get_os() == 'solaris':
+            base = '/usr/jdk/instances'
+            if exists(base):
+                candidateJdks = [join(base, n) for n in os.listdir(base)]
+        elif get_os() == 'windows':
+            base = r'C:\Program Files\Java'
+            if exists(base):
+                candidateJdks = [join(base, n) for n in os.listdir(base)]
+
+        configs = _filtered_jdk_configs(candidateJdks, versionCheck)
+    else:
+        if not isDefaultJdk:
+            return result
+        configs = [result]
+
+    if len(configs) > 1:
+        if not is_interactive():
+            msg = "Multiple possible choices for a JDK"
+            if purpose:
+                msg += ' for' + purpose
+            msg += ': '
+            if versionDescription:
+                msg += '(' + versionDescription + ')'
+            selected = configs[0]
+            msg += ". Selecting " + str(selected)
+            log(msg)
+        else:
+            msg = 'Please select a '
+            if isDefaultJdk:
+                msg += 'default '
+            msg += 'JDK'
+            if purpose:
+                msg += ' for' + purpose
+            msg += ': '
+            if versionDescription:
+                msg += '(' + versionDescription + ')'
+            log(msg)
+            choices = configs + ['<other>']
+            if cancel:
+                choices.append('Cancel (' + cancel + ')')
+            selected = select_items(choices, allowMultiple=False)
+            if isinstance(selected, types.StringTypes) and selected == '<other>':
+                selected = None
+            if isinstance(selected, types.StringTypes) and selected == 'Cancel (' + cancel + ')':
+                return None
+    elif len(configs) == 1:
+        selected = configs[0]
+        msg = 'Selected ' + str(selected) + ' as '
+        if isDefaultJdk:
+            msg += 'default'
+        msg += 'JDK'
+        if versionDescription:
+            msg = msg + ' ' + versionDescription
+        if purpose:
+            msg += ' for' + purpose
+        log(msg)
+    else:
+        msg = 'Could not find any JDK'
+        if purpose:
+            msg += ' for' + purpose
+        msg += ' '
+        if versionDescription:
+            msg = msg + '(' + versionDescription + ')'
+        log(msg)
+        selected = None
+
+    while not selected:
+        jdkLocation = raw_input('Enter path of JDK: ')
+        selected = _find_jdk_in_candidates([jdkLocation], versionCheck, warn=True)
+
+    varName = 'JAVA_HOME' if isDefaultJdk else 'EXTRA_JAVA_HOMES'
+    allowMultiple = not isDefaultJdk
+    envPath = join(_primary_suite.mxDir, 'env')
+    if is_interactive() and ask_yes_no('Persist this setting by adding "{0}={1}" to {2}'.format(varName, selected.jdk, envPath), 'y'):
+        envLines = []
+        with open(envPath) as fp:
+            append = True
+            for line in fp:
+                if line.rstrip().startswith(varName):
+                    _, currentValue = line.split('=', 1)
+                    currentValue = currentValue.strip()
+                    if not allowMultiple and currentValue:
+                        if not ask_yes_no('{0} is already set to {1}, overwrite with {2}?'.format(varName, currentValue, selected.jdk), 'n'):
+                            return selected
+                        else:
+                            line = varName + '=' + selected.jdk + os.linesep
+                    else:
+                        line = line.rstrip()
+                        if currentValue:
+                            line += os.pathsep
+                        line += selected.jdk + os.linesep
+                    append = False
+                envLines.append(line)
+        if append:
+            envLines.append(varName + '=' + selected.jdk)
+
+        with open(envPath, 'w') as fp:
+            for line in envLines:
+                fp.write(line)
+
+    if varName == 'JAVA_HOME':
+        os.environ['JAVA_HOME'] = selected.jdk
+
+    return selected
+
+def is_interactive():
+    return sys.__stdin__.isatty()
+
+def _filtered_jdk_configs(candidates, versionCheck, warn=False, source=None):
+    filtered = []
+    for candidate in candidates:
+        try:
+            config = JavaConfig(candidate)
+            if versionCheck(config.version):
+                filtered.append(config)
+        except JavaConfigException as e:
+            if warn:
+                log('Path in ' + source + "' is not pointing to a JDK (" + e.message + ")")
+    return filtered
+
+def _find_jdk_in_candidates(candidates, versionCheck, warn=False, source=None):
+    filtered = _filtered_jdk_configs(candidates, versionCheck, warn, source)
+    if filtered:
+        return filtered[0]
     return None
 
 
@@ -2079,6 +2226,10 @@
     def __hash__(self):
         return self.value.__hash__()
 
+    def exactMatch(self, version):
+        assert isinstance(version, VersionSpec)
+        return len(version.parts) > 1 and version.parts[0] == 1 and version.parts[1] == self.value
+
 """
 A version specification as defined in JSR-56
 """
@@ -2102,13 +2253,16 @@
         return os.pathsep.join([path for path in _separatedCygpathW2U(paths).split(os.pathsep) if exists(path)])
     return None
 
+class JavaConfigException(Exception):
+    def __init__(self, value):
+        Exception.__init__(self, value)
+
 """
 A JavaConfig object encapsulates info on how Java commands are run.
 """
 class JavaConfig:
-    def __init__(self, java_home, java_dbg_port):
+    def __init__(self, java_home):
         self.jdk = java_home
-        self.debug_port = java_dbg_port
         self.jar = exe_suffix(join(self.jdk, 'bin', 'jar'))
         self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
@@ -2122,7 +2276,7 @@
         self._endorseddirs = None
 
         if not exists(self.java):
-            abort('Java launcher does not exist: ' + self.java)
+            raise JavaConfigException('Java launcher does not exist: ' + self.java)
 
         def delAtAndSplit(s):
             return shlex.split(s.lstrip('@'))
@@ -2139,8 +2293,7 @@
             try:
                 output = subprocess.check_output([self.java, '-version'], stderr=subprocess.STDOUT)
             except subprocess.CalledProcessError as e:
-                print e.output
-                abort(e.returncode)
+                raise JavaConfigException(e.returncode + " :" + e.output)
 
         def _checkOutput(out):
             return 'version' in out
@@ -2156,8 +2309,8 @@
         self.version = VersionSpec(version.split()[2].strip('"'))
         self.javaCompliance = JavaCompliance(self.version.versionString)
 
-        if self.debug_port is not None:
-            self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)]
+        if _opts.java_dbg_port is not None:
+            self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)]
 
     def _init_classpaths(self):
         if not self._classpaths_initialized:
@@ -2180,7 +2333,7 @@
             self._classpaths_initialized = True
 
     def __repr__(self):
-        return "JavaConfig(" + str(self.jdk) + ", " + str(self.debug_port) + ")"
+        return "JavaConfig(" + str(self.jdk) + ")"
 
     def __str__(self):
         return "Java " + str(self.version) + " (" + str(self.javaCompliance) + ") from " + str(self.jdk)
@@ -2475,8 +2628,8 @@
                     self.logCompilation('javac' if not args.alt_javac else args.alt_javac)
                     javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir]
                     jdk.javacLibOptions(javacCmd)
-                    if jdk.debug_port is not None:
-                        javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
+                    if _opts.java_dbg_port is not None:
+                        javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(_opts.java_dbg_port)]
                     javacCmd += processorArgs
                     javacCmd += ['@' + _cygpathU2W(argfile.name)]
 
@@ -2636,7 +2789,6 @@
         # skip building this Java project if its Java compliance level is "higher" than the configured JDK
         requiredCompliance = p.javaCompliance if p.javaCompliance else JavaCompliance(args.compliance) if args.compliance else None
         jdk = java(requiredCompliance)
-        assert jdk
 
         outputDir = p.output_dir()
 
@@ -2940,16 +3092,33 @@
         def __init__(self, settingsDir, javaCompliance):
             self.path = join(settingsDir, 'org.eclipse.jdt.core.prefs')
             self.javaCompliance = javaCompliance
-            self.javafiles = list()
             with open(join(settingsDir, 'org.eclipse.jdt.ui.prefs')) as fp:
                 jdtUiPrefs = fp.read()
             self.removeTrailingWhitespace = 'sp_cleanup.remove_trailing_whitespaces_all=true' in jdtUiPrefs
             if self.removeTrailingWhitespace:
                 assert 'sp_cleanup.remove_trailing_whitespaces=true' in jdtUiPrefs and 'sp_cleanup.remove_trailing_whitespaces_ignore_empty=false' in jdtUiPrefs
-
-        def settings(self):
+            self.cachedHash = None
+
+        def __hash__(self):
+            if not self.cachedHash:
+                with open(self.path) as fp:
+                    self.cachedHash = (fp.read(), self.javaCompliance, self.removeTrailingWhitespace).__hash__()
+            return self.cachedHash
+
+        def __eq__(self, other):
+            if not isinstance(other, Batch):
+                return False
+            if self.removeTrailingWhitespace != other.removeTrailingWhitespace:
+                return False
+            if self.javaCompliance != other.javaCompliance:
+                return False
+            if self.path == other.path:
+                return True
             with open(self.path) as fp:
-                return fp.read() + java(self.javaCompliance).java + str(self.removeTrailingWhitespace)
+                with open(other.path) as ofp:
+                    if fp.read() != ofp.read():
+                        return False
+            return True
 
     class FileInfo:
         def __init__(self, path):
@@ -2992,22 +3161,22 @@
             if _opts.verbose:
                 log('[no Eclipse Code Formatter preferences at {0} - skipping]'.format(batch.path))
             continue
-
+        javafiles = []
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 for f in [join(root, name) for name in files if name.endswith('.java')]:
-                    batch.javafiles.append(FileInfo(f))
-        if len(batch.javafiles) == 0:
+                    javafiles.append(FileInfo(f))
+        if len(javafiles) == 0:
             logv('[no Java sources in {0} - skipping]'.format(p.name))
             continue
 
-        res = batches.setdefault(batch.settings(), batch)
-        if res is not batch:
-            res.javafiles = res.javafiles + batch.javafiles
+        res = batches.setdefault(batch, javafiles)
+        if res is not javafiles:
+            res.extend(javafiles)
 
     log("we have: " + str(len(batches)) + " batches")
-    for batch in batches.itervalues():
-        for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path):
+    for batch, javafiles in batches.iteritems():
+        for chunk in _chunk_files_for_command_line(javafiles, pathFunction=lambda f: f.path):
             run([args.eclipse_exe,
                 '-nosplash',
                 '-application',
@@ -4721,7 +4890,7 @@
 
 def fsckprojects(args):
     """find directories corresponding to deleted Java projects and delete them"""
-    if not sys.stdout.isatty():
+    if not is_interactive():
         log('fsckprojects command must be run in an interactive shell')
         return
     hg = HgConfig()
@@ -4746,7 +4915,7 @@
                     indicatorsInHg = hg.locate(suite.dir, indicators)
                     # Only proceed if there are indicator files that are not under HG
                     if len(indicators) > len(indicatorsInHg):
-                        if not sys.stdout.isatty() or ask_yes_no(dirpath + ' looks like a removed project -- delete it', 'n'):
+                        if not is_interactive() or ask_yes_no(dirpath + ' looks like a removed project -- delete it', 'n'):
                             shutil.rmtree(dirpath)
                             log('Deleted ' + dirpath)
 
@@ -4865,6 +5034,7 @@
                 # Once https://bugs.openjdk.java.net/browse/JDK-8041628 is fixed,
                 # this should be reverted to:
                 # javadocExe = java().javadoc
+                # we can then also respect _opts.relatex_compliance
                 javadocExe = projectJava.javadoc
 
                 run([javadocExe, memory,
@@ -5085,15 +5255,17 @@
     if len(items) <= 1:
         return items
     else:
+        assert is_interactive()
+        numlen = str(len(str(len(items))))
         if allowMultiple:
-            log('[0] <all>')
+            log(('[{0:>' + numlen + '}] <all>').format(0))
         for i in range(0, len(items)):
             if descriptions is None:
-                log('[{0}] {1}'.format(i + 1, items[i]))
+                log(('[{0:>' + numlen + '}] {1}').format(i + 1, items[i]))
             else:
                 assert len(items) == len(descriptions)
                 wrapper = textwrap.TextWrapper(subsequent_indent='    ')
-                log('\n'.join(wrapper.wrap('[{0}] {1} - {2}'.format(i + 1, items[i], descriptions[i]))))
+                log('\n'.join(wrapper.wrap(('[{0:>' + numlen + '}] {1} - {2}').format(i + 1, items[i], descriptions[i]))))
         while True:
             if allowMultiple:
                 s = raw_input('Enter number(s) of selection (separate multiple choices with spaces): ').split()
@@ -5265,7 +5437,7 @@
 def ask_yes_no(question, default=None):
     """"""
     assert not default or default == 'y' or default == 'n'
-    if not sys.stdout.isatty():
+    if not is_interactive():
         if default:
             return default
         else:
@@ -5395,16 +5567,6 @@
     opts, commandAndArgs = _argParser._parse_cmd_line()
     assert _opts == opts
 
-    global _java_homes
-    defaultJdk = JavaConfig(opts.java_home, opts.java_dbg_port)
-    _java_homes = [defaultJdk]
-    if opts.extra_java_homes:
-        for java_home in opts.extra_java_homes.split(os.pathsep):
-            extraJdk = JavaConfig(java_home, opts.java_dbg_port)
-            if extraJdk.javaCompliance > defaultJdk.javaCompliance:
-                abort('Secondary JDK ' + extraJdk.jdk + ' has higher compliance level than default JDK ' + defaultJdk.jdk)
-            _java_homes.append(extraJdk)
-
     for s in suites():
         s._post_init(opts)
 
--- a/src/share/vm/code/nmethod.cpp	Sat May 02 14:36:00 2015 -0700
+++ b/src/share/vm/code/nmethod.cpp	Sat May 02 14:40:49 2015 -0700
@@ -3536,7 +3536,7 @@
       installedCodeName = InstalledCode::name(installedCode);
     }
     if (installedCodeName != NULL) {
-      return java_lang_String::as_utf8_string(installedCodeName, buf, buflen);
+      return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
     } else {
       jio_snprintf(buf, buflen, "null");
       return buf;