# HG changeset patch # User Doug Simon # Date 1340221105 -7200 # Node ID 77069a28a9837754adeefc16ffb12130b1d1d63b # Parent 13166af0809ee4d2b7819ef86f31b5f991b10dfa split lowering of NEW into two separate nodes - one for doing the allocation and one for doing the object formatting. Both of these nodes are in turn lowered via snippets. diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jun 20 18:12:50 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jun 20 21:38:25 2012 +0200 @@ -229,7 +229,6 @@ @Override public void lower(Node n, CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) n.graph(); - if (n instanceof ArrayLengthNode) { ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID); @@ -367,6 +366,10 @@ if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) { newInstanceSnippets.lower((NewInstanceNode) n, tool); } + } else if (n instanceof TLABAllocateNode) { + newInstanceSnippets.lower((TLABAllocateNode) n, tool); + } else if (n instanceof InitializeNode) { + newInstanceSnippets.lower((InitializeNode) n, tool); } else { assert false : "Node implementing Lowerable not handled: " + n; } diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java Wed Jun 20 21:38:25 2012 +0200 @@ -0,0 +1,66 @@ +/* + * 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.api.meta.*; +import com.oracle.graal.cri.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Initializes the header and body of an uninitialized object cell. + * This node calls out to a stub to do both the allocation and formatting + * if the memory address it is given is zero/null (e.g. due to + * {@linkplain TLABAllocateNode TLAB allocation} failing). + */ +public final class InitializeNode extends FixedWithNextNode implements Lowerable { + + @Input private final ValueNode memory; + private final ResolvedJavaType type; + + public InitializeNode(ValueNode memory, ResolvedJavaType type) { + super(StampFactory.exactNonNull(type)); + this.memory = memory; + this.type = type; + } + + public ValueNode memory() { + return memory; + } + + public ResolvedJavaType type() { + return type; + } + + @Override + public void lower(CiLoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object initialize(Object memory, @ConstantNodeParameter ResolvedJavaType type) { + throw new UnsupportedOperationException(); + } +} diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Wed Jun 20 21:38:25 2012 +0200 @@ -0,0 +1,61 @@ +/* + * 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.api.meta.*; +import com.oracle.graal.cri.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Allocates some uninitialized area. This is used for TLAB allocation + * only. If allocation fails, zero/null is produced by this node. + */ +public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable { + + private final int size; + + public TLABAllocateNode(int size, Kind wordKind) { + super(StampFactory.forKind(wordKind)); + this.size = size; + } + + public int size() { + return size; + } + + @Override + public void lower(CiLoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + /** + * @return null if allocation fails + */ + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) { + throw new UnsupportedOperationException(); + } +} diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Wed Jun 20 18:12:50 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Wed Jun 20 21:38:25 2012 +0200 @@ -55,38 +55,32 @@ */ public class NewInstanceSnippets implements SnippetsInterface { - private static final boolean LOG_ALLOCATION = Boolean.getBoolean("graal.traceAllocation"); + @Snippet + public static Object allocate(@ConstantParameter("size") int size) { + Word thread = asWord(register(r15, wordKind())); + Word top = loadWord(thread, threadTlabTopOffset()); + Word end = loadWord(thread, threadTlabEndOffset()); + Word newTop = top.plus(size); + if (newTop.cmp(BE, end)) { + Object memory = cast(top, Object.class); + store(thread, 0, threadTlabTopOffset(), newTop); + return memory; + } + return null; + } @Snippet - public static Object newInstance( + public static Object initialize( + @Parameter("memory") Object memory, @Parameter("hub") Object hub, - @ConstantParameter("size") int size, - @ConstantParameter("useTLAB") boolean useTLAB, - @ConstantParameter("logType") String logType) { + @ConstantParameter("size") int size) { - if (useTLAB) { - Word thread = asWord(register(r15, wordKind())); - Word top = loadWord(thread, threadTlabTopOffset()); - Word end = loadWord(thread, threadTlabEndOffset()); - Word newTop = top.plus(size); - if (newTop.cmp(BE, end)) { - Object instance = cast(top, Object.class); - store(thread, 0, threadTlabTopOffset(), newTop); - formatInstance(hub, size, instance); - if (logType != null) { - Log.print(logType); - Log.print(" - fast alloc at "); - Log.printlnAddress(instance); - } - return verifyOop(instance); - } + if (memory == null) { + return NewInstanceStubCall.call(hub); } - - if (logType != null) { - Log.print(logType); - Log.println(" - slow alloc"); - } - return verifyOop(NewInstanceStubCall.call(hub)); + Object instance = cast(memory, Object.class); + formatInstance(hub, size, instance); + return verifyOop(instance); } private static Object verifyOop(Object object) { @@ -155,7 +149,8 @@ public static class Templates { private final Cache cache; - private final ResolvedJavaMethod newInstance; + private final ResolvedJavaMethod allocate; + private final ResolvedJavaMethod initialize; private final CodeCacheProvider runtime; private final boolean useTLAB; @@ -164,7 +159,8 @@ this.cache = new Cache(runtime); this.useTLAB = useTLAB; try { - newInstance = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("newInstance", Object.class, int.class, boolean.class, String.class)); + allocate = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("allocate", int.class)); + initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Object.class, Object.class, int.class)); } catch (NoSuchMethodException e) { throw new GraalInternalError(e); } @@ -178,16 +174,51 @@ StructuredGraph graph = (StructuredGraph) newInstanceNode.graph(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); HotSpotKlassOop hub = type.klassOop(); - int instanceSize = type.instanceSize(); - assert (instanceSize % wordSize()) == 0; - assert instanceSize >= 0; - Key key = new Key(newInstance).add("size", instanceSize).add("useTLAB", useTLAB).add("logType", LOG_ALLOCATION ? type.name() : null); - Arguments arguments = arguments("hub", hub); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + + ValueNode memory; + if (!useTLAB) { + memory = ConstantNode.forObject(null, runtime, graph); + } else { + TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind())); + graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); + memory = tlabAllocateNode; + } + InitializeNode initializeNode = graph.add(new InitializeNode(memory, type)); + graph.replaceFixedWithFixed(newInstanceNode, initializeNode); + } + + @SuppressWarnings("unused") + public void lower(TLABAllocateNode tlabAllocateNode, CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); + int size = tlabAllocateNode.size(); + assert (size % wordSize()) == 0; + assert size >= 0; + Key key = new Key(allocate).add("size", size); + Arguments arguments = new Arguments(); SnippetTemplate template = cache.get(key); - Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments); - //System.out.printf("Lowering newInstance in %s: node=%s, template=%s, arguments=%s%n", graph, newInstanceNode, template, arguments); - //DebugScope.getConfig().addToContext(graph.method()); - template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); + template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); + new DeadCodeEliminationPhase().apply(graph); + } + + @SuppressWarnings("unused") + public void lower(InitializeNode initializeNode, CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) initializeNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); + HotSpotKlassOop hub = type.klassOop(); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + Key key = new Key(initialize).add("size", size); + ValueNode memory = initializeNode.memory(); + //assert memory instanceof AllocateNode || memory instanceof ConstantNode : memory; + Arguments arguments = arguments("memory", memory).add("hub", hub); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering initialize in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + template.instantiate(runtime, initializeNode, initializeNode, arguments); new DeadCodeEliminationPhase().apply(graph); } } diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Wed Jun 20 18:12:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Wed Jun 20 21:38:25 2012 +0200 @@ -61,6 +61,10 @@ setCache(Kind.Void, voidStamp); } + public static Stamp forWord(Kind wordKind, boolean nonNull) { + return new WordStamp(wordKind, nonNull); + } + public static Stamp forKind(Kind kind) { assert stampCache[kind.stackKind().ordinal()] != null : "unexpected forKind(" + kind + ")"; return stampCache[kind.stackKind().ordinal()]; diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/WordStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/WordStamp.java Wed Jun 20 21:38:25 2012 +0200 @@ -0,0 +1,89 @@ +/* + * 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.nodes.type; + +import com.oracle.graal.api.meta.*; + +/** + * Models the word type. + */ +public class WordStamp extends Stamp { + + private final boolean nonNull; + + public WordStamp(Kind wordKind, boolean nonNull) { + super(wordKind); + this.nonNull = nonNull; + } + + @Override + public boolean nonNull() { + return nonNull; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(kind().typeChar); + str.append(nonNull ? "!" : ""); + return str.toString(); + } + + @Override + public boolean alwaysDistinct(Stamp otherStamp) { + return false; + } + + @Override + public Stamp meet(Stamp otherStamp) { + WordStamp other = (WordStamp) otherStamp; + if (other.nonNull == nonNull) { + return this; + } else { + return new WordStamp(kind(), nonNull && other.nonNull); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (nonNull ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + WordStamp other = (WordStamp) obj; + if (nonNull != other.nonNull) { + return false; + } + return true; + } +} diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Jun 20 18:12:50 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Jun 20 21:38:25 2012 +0200 @@ -135,6 +135,14 @@ } public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + StructuredGraph graph = parseGraph(method, policy); + + Debug.dump(graph, "%s: Final", method.name()); + + return graph; + } + + private StructuredGraph parseGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { StructuredGraph graph = graphCache.get(method); if (graph == null) { graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy); @@ -161,7 +169,7 @@ MethodCallTargetNode callTarget = invoke.callTarget(); ResolvedJavaMethod callee = callTarget.targetMethod(); if (policy.shouldInline(callee, method)) { - StructuredGraph targetGraph = makeGraph(callee, policy); + StructuredGraph targetGraph = parseGraph(callee, policy); InliningUtil.inline(invoke, targetGraph, true); Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { @@ -190,9 +198,6 @@ new DeadCodeEliminationPhase().apply(graph); new ComputeProbabilityPhase().apply(graph); } - - Debug.dump(graph, "%s: Final", method.name()); - return graph; } }); diff -r 13166af0809e -r 77069a28a983 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Wed Jun 20 18:12:50 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Wed Jun 20 21:38:25 2012 +0200 @@ -119,7 +119,7 @@ } ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); if (folding || CodeUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { - assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + ": " + argument; + assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument; ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant(); Object o = constant.boxedValue();