Mercurial > hg > graal-compiler
changeset 4431:73f56093d824
Merge
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Fri, 03 Feb 2012 10:21:02 +0100 |
parents | be4914c1c799 (diff) c97f09b8d1ce (current diff) |
children | 12558f571128 |
files | graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java |
diffstat | 14 files changed, 320 insertions(+), 71 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Fri Feb 03 10:21:02 2012 +0100 @@ -77,11 +77,11 @@ XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type); - XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact); - XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact); - XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type); + XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, XirArgument[] hintHubs, boolean hintsExact); XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Feb 03 10:21:02 2012 +0100 @@ -126,6 +126,7 @@ public static int MatureInvocationCount = 100; public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; + public static boolean UseInstanceOfHints = true; public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Feb 03 10:21:02 2012 +0100 @@ -480,12 +480,27 @@ @Override public void visitCheckCast(CheckCastNode x) { - XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass()); + XirArgument[] hints = getTypeCheckHints(x); + XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), hints, x.hintsExact()); emitXir(snippet, x, state(), true); // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it. setResult(x, operand(x.object())); } + private XirArgument[] getTypeCheckHints(TypeCheckNode x) { + XirArgument[] hints; + if (!GraalOptions.UseInstanceOfHints || x.hints() == null || x.hints().length == 0) { + hints = new XirArgument[0]; + } else { + assert x.hints().length == x.hintInstructions().size(); + hints = new XirArgument[x.hints().length]; + for (int i = 0; i < x.hints().length; i++) { + hints[i] = toXirArgument(x.hintInstructions().get(i)); + } + } + return hints; + } + @Override public void visitMonitorEnter(MonitorEnterNode x) { CiStackSlot lockData = frameMap.allocateStackBlock(runtime.sizeOfLockData(), false); @@ -739,8 +754,9 @@ } private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { + XirArgument[] hints = getTypeCheckHints(x); XirArgument obj = toXirArgument(x.object()); - XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass()); + XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), hints, x.hintsExact()); emitXir(snippet, x, info, null, false, x.negated() ? falseSuccessor : trueSuccessor, x.negated() ? trueSuccessor : falseSuccessor); } @@ -782,10 +798,11 @@ } private Variable emitInstanceOfConditional(InstanceOfNode x, CiValue trueValue, CiValue falseValue) { + XirArgument[] hints = getTypeCheckHints(x); XirArgument obj = toXirArgument(x.object()); XirArgument trueArg = toXirArgument(x.negated() ? falseValue : trueValue); XirArgument falseArg = toXirArgument(x.negated() ? trueValue : falseValue); - XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass()); + XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), hints, x.hintsExact()); return (Variable) emitXir(snippet, null, null, false); }
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Fri Feb 03 10:21:02 2012 +0100 @@ -103,6 +103,7 @@ public static void dump(Object object, String msg, Object... args) { if (ENABLED && DebugScope.getInstance().isDumpEnabled()) { + System.out.println("dumping"); DebugScope.getInstance().dump(object, msg, args); } } @@ -144,7 +145,7 @@ } } - public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled) { + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final List<DebugDumpHandler> dumpHandlers) { return new DebugConfig() { @Override @@ -174,7 +175,7 @@ @Override public Collection< ? extends DebugDumpHandler> dumpHandlers() { - return Collections.emptyList(); + return dumpHandlers; } }; }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java Fri Feb 03 10:21:02 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.graph; +import java.util.*; + public final class NodeInputList<T extends Node> extends NodeList<T> { @@ -42,6 +44,12 @@ this.self = self; } + public NodeInputList(Node self, List<? extends T> elements) { + super(elements); + assert self.usages() == null; + this.self = self; + } + @Override protected void update(T oldNode, T newNode) { self.updateUsages(oldNode, newNode);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java Fri Feb 03 10:21:02 2012 +0100 @@ -64,6 +64,21 @@ } } + protected NodeList(List<? extends T> elements) { + if (elements == null || elements.isEmpty()) { + this.size = 0; + this.nodes = EMPTY_NODE_ARRAY; + this.initialSize = 0; + } else { + this.size = elements.size(); + this.initialSize = elements.size(); + this.nodes = new Node[elements.size()]; + for (int i = 0; i < elements.size(); i++) { + this.nodes[i] = elements.get(i); + } + } + } + protected abstract void update(T oldNode, T newNode); @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Fri Feb 03 10:21:02 2012 +0100 @@ -90,7 +90,7 @@ for (Object o : Debug.context()) { if (o instanceof RiMethod) { RiMethod riMethod = (RiMethod) o; - if (riMethod.toString().contains(methodFilter)) { + if (CiUtil.format("%H.%n", riMethod).contains(methodFilter)) { return true; } } @@ -125,7 +125,7 @@ if (e instanceof CiBailout) { return e; } - Debug.setConfig(Debug.fixedConfig(true, true, false, false)); + Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers)); // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__ Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Fri Feb 03 10:21:02 2012 +0100 @@ -231,12 +231,20 @@ @Override public void compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable { try { - if (Thread.currentThread() instanceof CompilerThread && method.holder().name().contains("java/util/concurrent")) { - // This is required to avoid deadlocking a compiler thread. The issue is that a - // java.util.concurrent.BlockingQueue is used to implement the compilation worker - // queues. If a compiler thread triggers a compilation, then it may be blocked trying - // to add something to its own queue. - return; + if (Thread.currentThread() instanceof CompilerThread) { + if (method.holder().name().contains("java/util/concurrent")) { + // This is required to avoid deadlocking a compiler thread. The issue is that a + // java.util.concurrent.BlockingQueue is used to implement the compilation worker + // queues. If a compiler thread triggers a compilation, then it may be blocked trying + // to add something to its own queue. + return; + } + } else { + if (GraalOptions.Debug) { + Debug.enable(); + HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter); + Debug.setConfig(hotspotDebugConfig); + } } Runnable runnable = new Runnable() {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Fri Feb 03 10:21:02 2012 +0100 @@ -637,10 +637,10 @@ } }; - private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -657,14 +657,34 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jneq(slowPath, objHub, hub); - asm.bindInline(end); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(slowPath, objHub, asm.o(null)); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + } else { + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(end, objHub, hintHub); + } else { + asm.jneq(slowPath, objHub, hintHub); + } + } + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + if (!is(EXACT_HINTS, flags)) { + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + } + } + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); asm.mov(scratch, wordConst(asm, 2)); @@ -675,10 +695,10 @@ } }; - private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -686,7 +706,6 @@ XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); @@ -696,24 +715,48 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } else { + XirLabel slowPath = null; - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(trueSucc, objHub, hintHub); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jneq(falseSucc, objHub, hintHub); + asm.jmp(trueSucc); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jneq(slowPath, objHub, hintHub); + asm.jmp(trueSucc); + } + } + } + + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } + } return asm.finishTemplate("instanceof"); } }; - private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { XirOperand result = asm.restart(CiKind.Int); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -723,10 +766,8 @@ XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - XirLabel trueSucc = asm.createInlineLabel("ok"); + XirLabel end = asm.createInlineLabel("end"); XirLabel falseSucc = asm.createInlineLabel("ko"); - XirLabel end = asm.createInlineLabel("end"); if (is(NULL_CHECK, flags)) { // null isn't "instanceof" anything @@ -734,22 +775,45 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); + asm.mov(result, trueValue); + + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + } else { + XirLabel slowPath = null; - asm.bindInline(trueSucc); - asm.mov(result, trueValue); - asm.jmp(end); - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(end, objHub, hintHub); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jeq(end, objHub, hintHub); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jeq(end, objHub, hintHub); + asm.jmp(slowPath); + } + } + } + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(end); + } + } return asm.finishTemplate("instanceof"); } @@ -1253,18 +1317,56 @@ } @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - return new XirSnippet(checkCastTemplates.get(site), receiver, hub); + public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact) { + System.out.print(hintsExact ? "+" : "-"); + if (hintHubs == null || hintHubs.length == 0) { + return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + } else { + XirArgument[] params = new XirArgument[hintHubs.length + 2]; + params[0] = receiver; + params[1] = hub; + for (int i = 0; i < hintHubs.length; i++) { + params[i + 2] = hintHubs[i]; + } + XirTemplate template = hintsExact ? checkCastTemplates.get(site, hintHubs.length, EXACT_HINTS) : checkCastTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { - return new XirSnippet(instanceOfTemplates.get(site), object, hub); + public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact) { + System.out.print(hintsExact ? "+" : "-"); + if (hintHubs == null || hintHubs.length == 0) { + return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub); + } else { + XirArgument[] params = new XirArgument[hintHubs.length + 2]; + params[0] = object; + params[1] = hub; + for (int i = 0; i < hintHubs.length; i++) { + params[i + 2] = hintHubs[i]; + } + XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : instanceOfTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) { - return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue); + public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, XirArgument[] hintHubs, boolean hintsExact) { + System.out.print(hintsExact ? "+" : "-"); + if (hintHubs == null || hintHubs.length == 0) { + return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue); + } else { + XirArgument[] params = new XirArgument[hintHubs.length + 4]; + params[0] = object; + params[1] = hub; + params[2] = trueValue; + params[3] = falseValue; + for (int i = 0; i < hintHubs.length; i++) { + params[i + 4] = hintHubs[i]; + } + XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Fri Feb 03 10:21:02 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.max.graal.hotspot.ri; enum TemplateFlag { - NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED; + NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS; private static final long FIRST_FLAG = 0x0000000100000000L; public static final long FLAGS_MASK = 0x0000FFFF00000000L;
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Fri Feb 03 10:21:02 2012 +0100 @@ -711,8 +711,43 @@ RiType type = lookupType(cpi, INSTANCEOF); ValueNode object = frameState.apop(); if (type instanceof RiResolvedType) { - ConstantNode hub = appendConstant(((RiResolvedType) type).getEncoding(RiType.Representation.ObjectHub)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(new InstanceOfNode(hub, (RiResolvedType) type, object, false)), currentGraph))); + RiResolvedType resolvedType = (RiResolvedType) type; + ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub)); + + final InstanceOfNode instanceOfNode; + if (!GraalOptions.UseInstanceOfHints) { + instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, false); + } else { + if (Modifier.isFinal(resolvedType.accessFlags()) || resolvedType.isArrayClass()) { + instanceOfNode = new InstanceOfNode(hub, resolvedType, object, Collections.singletonList(hub), new RiResolvedType[] {resolvedType}, true, false); + } else { + RiResolvedType uniqueSubtype = resolvedType.uniqueConcreteSubtype(); + if (uniqueSubtype != null) { +// TTY.println("unique concrete subtype: " + uniqueSubtype); + ConstantNode subTypeHub = appendConstant(uniqueSubtype.getEncoding(RiType.Representation.ObjectHub)); + instanceOfNode = new InstanceOfNode(hub, resolvedType, object, Collections.singletonList(subTypeHub), new RiResolvedType[] {uniqueSubtype}, false, false); + } else { + RiTypeProfile typeProfile = method.typeProfile(bci()); + if (typeProfile != null && typeProfile.types != null && typeProfile.types.length > 0) { + ArrayList<ValueNode> hintInstructions = new ArrayList<>(typeProfile.types.length); + RiResolvedType[] hints = new RiResolvedType[typeProfile.types.length]; + int hintCount = 0; + + for (RiResolvedType hint : typeProfile.types) { +// TTY.println("profiled type: " + hint); + if (hint.isSubtypeOf(resolvedType)) { + hintInstructions.add(appendConstant(hint.getEncoding(RiType.Representation.ObjectHub))); + hints[hintCount++] = hint; + } + } + instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hintInstructions, Arrays.copyOf(hints, hintCount), false, false); + } else { + instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, false); + } + } + } + } + frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile));
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Fri Feb 03 10:21:02 2012 +0100 @@ -22,8 +22,11 @@ */ package com.oracle.max.graal.nodes.java; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.extended.*; import com.oracle.max.graal.nodes.spi.*; @@ -32,10 +35,14 @@ /** * The {@code CheckCastNode} represents a {@link Bytecodes#CHECKCAST}. */ -public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable { +public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType { @Input protected final AnchorNode anchor; + public AnchorNode anchor() { + return anchor; + } + /** * Creates a new CheckCast instruction. * @@ -44,7 +51,12 @@ * @param object the instruction producing the object */ public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object) { - super(targetClassInstruction, targetClass, object, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); + this(anchor, targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false); + } + + public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact) { + super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); + assert targetClass != null; this.anchor = anchor; }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Fri Feb 03 10:21:02 2012 +0100 @@ -22,6 +22,9 @@ */ package com.oracle.max.graal.nodes.java; +import java.lang.reflect.*; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.nodes.*; @@ -48,7 +51,11 @@ * @param object the instruction producing the object input to this instruction */ public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean negated) { - super(targetClassInstruction, targetClass, object, StampFactory.illegal()); + this(targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false, negated); + } + + public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact, boolean negated) { + super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, StampFactory.illegal()); this.negated = negated; assert targetClass != null; } @@ -59,8 +66,23 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (object().exactType() != null) { - boolean result = object().exactType().isSubtypeOf(targetClass()); + RiResolvedType exact = object().exactType(); + + if (exact == null) { + if (object().declaredType() != null) { + if (Modifier.isFinal(object().declaredType().accessFlags()) || object().declaredType().isArrayClass()) { + exact = object().declaredType(); + } else if (tool.assumptions() != null) { + exact = object().declaredType().uniqueConcreteSubtype(); + if (exact != null) { + tool.assumptions().recordConcreteSubtype(object().declaredType(), exact); + } + } + } + } + + if (exact != null) { + boolean result = exact.isSubtypeOf(targetClass()); if (result != negated) { // The instanceof check reduces to a null check. return graph().unique(new NullCheckNode(object(), false)); @@ -78,11 +100,17 @@ assert false : "non-null constants are always expected to provide an exactType"; } } + if (tool.assumptions() != null && hints() != null && targetClass() != null) { + if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) { + tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]); + return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hintInstructions(), hints(), true, negated)); + } + } return this; } @Override public BooleanNode negate() { - return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), !negated)); + return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hintInstructions(), hints(), hintsExact(), !negated)); } }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Thu Feb 02 19:08:03 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Fri Feb 03 10:21:02 2012 +0100 @@ -22,7 +22,10 @@ */ package com.oracle.max.graal.nodes.java; +import java.util.*; + import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.type.*; @@ -31,9 +34,13 @@ */ public abstract class TypeCheckNode extends BooleanNode { + protected static final RiResolvedType[] EMPTY_HINTS = new RiResolvedType[0]; @Input private ValueNode object; @Input private ValueNode targetClassInstruction; + @Input private final NodeInputList<ValueNode> hintInstructions; @Data private final RiResolvedType targetClass; + @Data private final RiResolvedType[] hints; + @Data private final boolean hintsExact; /** * Creates a new TypeCheckNode. @@ -42,11 +49,14 @@ * @param object the node which produces the object * @param kind the result type of this node */ - public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, Stamp stamp) { + public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact, Stamp stamp) { super(stamp); this.targetClassInstruction = targetClassInstruction; this.targetClass = targetClass; this.object = object; + this.hintInstructions = new NodeInputList<>(this, hintInstructions); + this.hints = hints; + this.hintsExact = hintsExact; } public ValueNode object() { @@ -64,4 +74,16 @@ public RiResolvedType targetClass() { return targetClass; } + + public NodeInputList<ValueNode> hintInstructions() { + return hintInstructions; + } + + public RiResolvedType[] hints() { + return hints; + } + + public boolean hintsExact() { + return hintsExact; + } }