changeset 5472:fa979ebe0186

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 01 Jun 2012 16:54:27 +0200
parents c9b8994b43d8 (current diff) 7a0d58000ae0 (diff)
children af838558e9e5 5134cd2f25ed
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 3 files changed, 83 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java	Fri Jun 01 16:32:05 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/snippets/CheckCastSnippets.java	Fri Jun 01 16:32:05 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Fri Jun 01 16:54:27 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 16:32:05 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();
-    }
-}