changeset 5479:af838558e9e5

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Fri, 01 Jun 2012 17:27:38 +0200
parents 4a99bfc329f0 (current diff) fa979ebe0186 (diff)
children c89a69ca8dbb 64b1fceb4570
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java
diffstat 6 files changed, 83 insertions(+), 247 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java	Fri Jun 01 17:27:31 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2012, 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.hotspot.nodes;
-
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.target.amd64.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.max.cri.ci.*;
-
-/**
- * A node for calling the HotSpot stub implementing the slow path of a type check.
- * This stub does not use any registers.
- */
-public final class TypeCheckSlowPath extends FloatingNode implements LIRGenLowerable {
-
-    @Input private ValueNode objectHub;
-    @Input private ValueNode hub;
-
-    public ValueNode objectHub() {
-        return objectHub;
-    }
-
-    public ValueNode hub() {
-        return hub;
-    }
-
-    public TypeCheckSlowPath(ValueNode objectHub, ValueNode hub) {
-        super(StampFactory.forKind(CiKind.Boolean));
-        this.objectHub = objectHub;
-        this.hub = hub;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        CiValue objectHubOpr = gen.operand(objectHub);
-        Variable result = gen.newVariable(CiKind.Boolean);
-        AMD64TypeCheckSlowPathOp op = new AMD64TypeCheckSlowPathOp(result, objectHubOpr, gen.operand(hub));
-        gen.append(op);
-        gen.setResult(this, result);
-    }
-
-    /**
-     * Checks if {@code objectHub} is a subclass of {@code hub}.
-     *
-     * @return {@code true} if {@code objectHub} is a subclass of {@code hub}, {@code false} otherwise
-     */
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static boolean check(Object objectHub, Object hub) {
-        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
-    }
-
-
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri Jun 01 17:27:31 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri Jun 01 17:27:38 2012 +0200
@@ -194,11 +194,6 @@
     }
 
     @Override
-    public boolean isExceptionType(RiResolvedType type) {
-        return type.isSubtypeOf((RiResolvedType) compiler.getCompilerToVM().getType(Throwable.class));
-    }
-
-    @Override
     public int sizeOfLockData() {
         // TODO shouldn't be hard coded
         return 8;
@@ -234,16 +229,6 @@
     }
 
     @Override
-    public Class<?> asJavaClass(CiConstant c) {
-        return (Class<?>) c.asObject();
-    }
-
-    @Override
-    public Object asJavaObject(CiConstant c) {
-        return c.asObject();
-    }
-
-    @Override
     public void lower(Node n, CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Fri Jun 01 17:27:31 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Fri Jun 01 17:27:38 2012 +0200
@@ -59,10 +59,44 @@
 public class CheckCastSnippets implements SnippetsInterface {
 
     /**
-     * Type test used when the type being tested against is a restricted primary type.
+     * Type test used when the type being tested against is a final type.
      */
     @Snippet
-    public static Object checkcastPrimary(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull, int superCheckOffset) {
+    public static Object checkcastExact(Object object, Object exactHub, boolean checkNull) {
+        if (checkNull && object == null) {
+            return object;
+        }
+        Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true);
+        if (objectHub != exactHub) {
+            DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
+        }
+        return object;
+    }
+
+    /**
+     * Type test used when the type being tested against is a restricted primary type.
+     *
+     * This test ignores use of hints altogether as the display-based type check only
+     * involves one extra load where the second load should hit the same cache line as the
+     * first.
+     */
+    @Snippet
+    public static Object checkcastPrimary(Object hub, Object object, boolean checkNull, int superCheckOffset) {
+        if (checkNull && object == null) {
+            return object;
+        }
+        Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true);
+        if (UnsafeLoadNode.loadObject(objectHub, 0, superCheckOffset, true) != hub) {
+            DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
+        }
+        return object;
+    }
+
+    /**
+     * Type test used when the type being tested against is a restricted secondary type.
+     */
+    @Snippet
+    public static Object checkcastSecondary(Object hub, Object object, Object[] hintHubs, boolean checkNull) {
         if (checkNull && object == null) {
             return object;
         }
@@ -75,21 +109,18 @@
                 return object;
             }
         }
-        if (hintsAreExact) {
+        if (!checkSecondarySubType(hub, objectHub)) {
             DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-        } else {
-            if (UnsafeLoadNode.loadObject(objectHub, 0, superCheckOffset, true) != hub) {
-                DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-            }
         }
         return object;
     }
 
     /**
-     * Type test used when the type being tested against is a restricted secondary type.
+     * Type test used when the type being tested against is not known at compile time (e.g. the type test
+     * in an object array store check).
      */
     @Snippet
-    public static Object checkcastSecondary(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull) {
+    public static Object checkcastUnknown(Object hub, Object object, Object[] hintHubs, boolean checkNull) {
         if (checkNull && object == null) {
             return object;
         }
@@ -102,40 +133,8 @@
                 return object;
             }
         }
-        if (hintsAreExact) {
+        if (!checkUnknownSubType(hub, objectHub)) {
             DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-        } else {
-            if (!checkSecondarySubType(hub, objectHub)) {
-                DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-            }
-        }
-        return object;
-    }
-
-    /**
-     * Type test used when the type being tested against is not known at compile time (e.g. the type test
-     * in an object array store check).
-     */
-    @Snippet
-    public static Object checkcastUnknown(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull) {
-        if (checkNull && object == null) {
-            return object;
-        }
-        Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true);
-        // if we get an exact match: succeed immediately
-        ExplodeLoopNode.explodeLoop();
-        for (int i = 0; i < hintHubs.length; i++) {
-            Object hintHub = hintHubs[i];
-            if (hintHub == objectHub) {
-                return object;
-            }
-        }
-        if (hintsAreExact) {
-            DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-        } else {
-            if (!checkUnknownSubType(hub, objectHub)) {
-                DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
-            }
         }
         return object;
     }
@@ -206,7 +205,7 @@
     public enum Counter {
         hintsHit("hit a hint type"),
         hintsMissed("missed the hint types"),
-        exact("tested type is (statically) final"),
+        exactType("tested type is (statically) final"),
         noHints("profile information is not used"),
         isNull("object tested is null"),
         exception("type test failed with a ClassCastException");
@@ -267,7 +266,7 @@
                 Object hintHub = hintHubs[i];
                 if (hintHub == objectHub) {
                     if (hintsAreExact) {
-                        exact.inc();
+                        exactType.inc();
                     } else {
                         hintsHit.inc();
                     }
@@ -381,19 +380,21 @@
     public static class Templates {
 
         private final ConcurrentHashMap<Integer, SnippetTemplate> templates;
-        private final RiResolvedMethod counters;
+        private final RiResolvedMethod exact;
         private final RiResolvedMethod primary;
         private final RiResolvedMethod secondary;
         private final RiResolvedMethod unknown;
+        private final RiResolvedMethod counters;
         private final RiRuntime runtime;
 
         public Templates(RiRuntime runtime) {
             this.runtime = runtime;
             this.templates = new ConcurrentHashMap<>();
             try {
-                primary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastPrimary", Object.class, Object.class, Object[].class, boolean.class, boolean.class, int.class));
-                secondary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastSecondary", Object.class, Object.class, Object[].class, boolean.class, boolean.class));
-                unknown = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastUnknown", Object.class, Object.class, Object[].class, boolean.class, boolean.class));
+                exact = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastExact", Object.class, Object.class, boolean.class));
+                primary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastPrimary", Object.class, Object.class, boolean.class, int.class));
+                secondary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastSecondary", Object.class, Object.class, Object[].class, boolean.class));
+                unknown = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastUnknown", Object.class, Object.class, Object[].class, boolean.class));
                 counters = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastCounters", Object.class, Object.class, Object[].class, boolean.class));
             } catch (NoSuchMethodException e) {
                 throw new GraalInternalError(e);
@@ -428,6 +429,14 @@
             return result;
         }
 
+        private static HotSpotKlassOop[] createHintHubs(TypeCheckHints hints) {
+            HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length];
+            for (int i = 0; i < hintHubs.length; i++) {
+                hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop();
+            }
+            return hintHubs;
+        }
+
         /**
          * Lowers a checkcast node.
          */
@@ -436,16 +445,13 @@
             ValueNode hub = checkcast.targetClassInstruction();
             ValueNode object = checkcast.object();
             TypeCheckHints hints = new TypeCheckHints(checkcast.targetClass(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
-            HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length];
-            for (int i = 0; i < hintHubs.length; i++) {
-                hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop();
-            }
             Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact);
 
             final HotSpotTypeResolvedImpl target = (HotSpotTypeResolvedImpl) checkcast.targetClass();
-            int flags = EXACT_HINTS.bit(hints.exact) | CHECK_NULL.bit(!object.stamp().nonNull());
+            int flags = CHECK_NULL.bit(!object.stamp().nonNull());
             if (GraalOptions.CheckcastCounters) {
-                SnippetTemplate template = getTemplate(hintHubs.length, flags | COUNTERS.bit(), 0, new Factory() {
+                HotSpotKlassOop[] hintHubs = createHintHubs(hints);
+                SnippetTemplate template = getTemplate(hintHubs.length, flags | EXACT_HINTS.bit(hints.exact) | COUNTERS.bit(), 0, new Factory() {
                     @SuppressWarnings("hiding")
                     @Override
                     SnippetTemplate create(HotSpotKlassOop[] hints, int flags) {
@@ -455,32 +461,46 @@
                 });
                 template.instantiate(runtime, checkcast, checkcast, hub, object, hintHubs, hints.exact);
             } else if (target == null) {
+                HotSpotKlassOop[] hintHubs = createHintHubs(hints);
                 SnippetTemplate template = getTemplate(hintHubs.length, flags | UNKNOWN_SUPER.bit(), 0, new Factory() {
                     @SuppressWarnings("hiding")
                     @Override
                     SnippetTemplate create(HotSpotKlassOop[] hints, int flags) {
-                        // checkcastUnknown(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull)
-                        return SnippetTemplate.create(runtime, unknown, _, _, hints, EXACT_HINTS.bool(flags), CHECK_NULL.bool(flags));
+                        // checkcastUnknown(Object hub, Object object, Object[] hintHubs, boolean checkNull)
+                        return SnippetTemplate.create(runtime, unknown, _, _, hints, CHECK_NULL.bool(flags));
                     }
                 });
                 template.instantiate(runtime, checkcast, checkcast, hub, object, hintHubs);
-            } else if (target.isPrimaryType()) {
-                SnippetTemplate template = getTemplate(hintHubs.length, flags | PRIMARY_SUPER.bit(), target.superCheckOffset(), new Factory() {
+            } else if (hints.exact) {
+                HotSpotKlassOop[] hintHubs = createHintHubs(hints);
+                assert hintHubs.length == 1;
+                SnippetTemplate template = getTemplate(hintHubs.length, flags | EXACT_HINTS.bit(), 0, new Factory() {
                     @SuppressWarnings("hiding")
                     @Override
                     SnippetTemplate create(HotSpotKlassOop[] hints, int flags) {
-                        // checkcastPrimary(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull, int superCheckOffset)
-                        return SnippetTemplate.create(runtime, primary, _, _, hints, EXACT_HINTS.bool(flags), CHECK_NULL.bool(flags), target.superCheckOffset());
+                        // checkcastExact(Object object, Object exactHub, boolean checkNull)
+                        return SnippetTemplate.create(runtime, exact, _, hints[0], CHECK_NULL.bool(flags));
                     }
                 });
-                template.instantiate(runtime, checkcast, checkcast, hub, object, hintHubs);
+                template.instantiate(runtime, checkcast, checkcast, object, hintHubs[0]);
+            } else if (target.isPrimaryType()) {
+                SnippetTemplate template = getTemplate(0, flags | PRIMARY_SUPER.bit(), target.superCheckOffset(), new Factory() {
+                    @SuppressWarnings("hiding")
+                    @Override
+                    SnippetTemplate create(HotSpotKlassOop[] hints, int flags) {
+                        // checkcastPrimary(Object hub, Object object, boolean checkNull, int superCheckOffset)
+                        return SnippetTemplate.create(runtime, primary, _, _, CHECK_NULL.bool(flags), target.superCheckOffset());
+                    }
+                });
+                template.instantiate(runtime, checkcast, checkcast, hub, object);
             } else {
+                HotSpotKlassOop[] hintHubs = createHintHubs(hints);
                 SnippetTemplate template = getTemplate(hintHubs.length, flags | SECONDARY_SUPER.bit(), 0, new Factory() {
                     @SuppressWarnings("hiding")
                     @Override
                     SnippetTemplate create(HotSpotKlassOop[] hints, int flags) {
-                        // checkcastSecondary(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, boolean checkNull)
-                        return SnippetTemplate.create(runtime, secondary, _, _, hints, EXACT_HINTS.bool(flags), CHECK_NULL.bool(flags));
+                        // checkcastSecondary(Object hub, Object object, Object[] hintHubs, boolean checkNull)
+                        return SnippetTemplate.create(runtime, secondary, _, _, hints, CHECK_NULL.bool(flags));
                     }
                 });
                 template.instantiate(runtime, checkcast, checkcast, hub, object, hintHubs);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java	Fri Jun 01 17:27:31 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, 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.hotspot.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-
-/**
- * Performs a call to the {@code slow_subtype_check_id} stub.
- */
-public class AMD64TypeCheckSlowPathOp extends AMD64LIRInstruction {
-
-    public AMD64TypeCheckSlowPathOp(CiValue result, CiValue objectHub, CiValue hub) {
-        super("TYPECHECK_SLOW", new CiValue[] {result}, null, new CiValue[] {objectHub, hub}, NO_OPERANDS, NO_OPERANDS);
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        CiValue result = output(0);
-        CiValue objectHub = input(0);
-        CiValue hub = input(1);
-
-        masm.push(asRegister(objectHub));
-        masm.push(asRegister(hub));
-        AMD64Call.directCall(tasm, masm, CompilerImpl.getInstance().getConfig().instanceofStub, null);
-
-        // Two pops to balance the two pushes above - the value first popped is discarded
-        masm.pop(asRegister(result));
-        masm.pop(asRegister(result));
-    }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Output) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
-}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Fri Jun 01 17:27:31 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Fri Jun 01 17:27:38 2012 +0200
@@ -266,9 +266,6 @@
             } else if (param instanceof ConstantNode) {
                 replacements.put((ConstantNode) param, ConstantNode.forObject(arg, runtime, replaceeGraph));
             } else {
-                if (!param.equals(arg)) {
-                    System.exit(1);
-                }
                 assert param.equals(arg) : param + " != " + arg;
             }
         }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java	Fri Jun 01 17:27:31 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java	Fri Jun 01 17:27:38 2012 +0200
@@ -69,11 +69,6 @@
     RiResolvedType getType(Class<?> clazz);
 
     /**
-     * Returns true if the given type is a subtype of java/lang/Throwable.
-     */
-    boolean isExceptionType(RiResolvedType type);
-
-    /**
      * Used by the canonicalizer to compare objects, since a given runtime might not want to expose the real objects to the compiler.
      *
      * @return true if the two parameters represent the same runtime object, false otherwise
@@ -108,20 +103,6 @@
     int getArrayLength(CiConstant array);
 
     /**
-     * Converts the given CiConstant object to a object.
-     *
-     * @return {@code null} if the conversion is not possible <b>OR</b> {@code c.isNull() == true}
-     */
-    Object asJavaObject(CiConstant c);
-
-    /**
-     * Converts the given CiConstant object to a {@link Class} object.
-     *
-     * @return {@code null} if the conversion is not possible.
-     */
-    Class<?> asJavaClass(CiConstant c);
-
-    /**
      * Performs any runtime-specific conversion on the object used to describe the target of a call.
      */
     Object asCallTarget(Object target);