Mercurial > hg > truffle
changeset 7766:e393b8156c42
Merge
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Mon, 11 Feb 2013 10:46:48 +0100 |
parents | f20c2b1f5289 (diff) 52fd6491fca8 (current diff) |
children | 4a6646d8eb87 |
files | graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/AMD64AssemblerTest.java |
diffstat | 26 files changed, 432 insertions(+), 57 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Feb 11 10:46:48 2013 +0100 @@ -74,7 +74,7 @@ /** * Denotes that a parameter of an {@linkplain NodeIntrinsic intrinsic} method must be a compile - * time constant at all call sites to the intrinic method. + * time constant at all call sites to the intrinsic method. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Feb 11 10:46:48 2013 +0100 @@ -287,6 +287,7 @@ public int layoutHelperLog2ElementSizeMask; public int layoutHelperElementTypeShift; public int layoutHelperElementTypeMask; + public int layoutHelperElementTypePrimitiveInPlace; public int layoutHelperHeaderSizeShift; public int layoutHelperHeaderSizeMask; public int layoutHelperOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Feb 11 10:46:48 2013 +0100 @@ -350,6 +350,9 @@ if (GraalOptions.IntrinsifyArrayCopy) { installer.installSnippets(ArrayCopySnippets.class); } + if (GraalOptions.IntrinsifyObjectClone) { + installer.installSnippets(ObjectCloneSnippets.class); + } installer.installSnippets(CheckCastSnippets.class); installer.installSnippets(InstanceOfSnippets.class); @@ -705,7 +708,7 @@ assert loadHub.kind() == wordKind; LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); ValueNode object = loadHub.object(); - assert !object.isConstant(); + assert !object.isConstant() || object.asConstant().isNull(); ValueNode guard = tool.createNullCheckGuard(object); ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()))); hub.dependencies().add(guard);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Mon Feb 11 10:46:48 2013 +0100 @@ -256,7 +256,7 @@ long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift; long count = end - start + 1; while (count-- > 0) { - DirectStoreNode.store((start + cardStart) + count, false); + DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Feb 11 10:46:48 2013 +0100 @@ -442,6 +442,12 @@ return config().layoutHelperElementTypeMask; } + @Fold + public static int layoutHelperElementTypePrimitiveInPlace() { + System.out.println(String.format("%x", config().layoutHelperElementTypePrimitiveInPlace)); + return config().layoutHelperElementTypePrimitiveInPlace; + } + static { assert arrayIndexScale(Kind.Byte) == 1; assert arrayIndexScale(Kind.Boolean) == 1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013, 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.snippets; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.snippets.nodes.*; + +public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider { + + public ObjectCloneNode(Invoke invoke) { + super(invoke); + } + + @Override + public boolean inferStamp() { + return updateStamp(getObject().stamp()); + } + + private ValueNode getObject() { + return arguments.get(0); + } + + private Method selectSnippetMethod(LoweringTool tool) { + ResolvedJavaType type = getObject().objectStamp().type(); + if (type.isArray()) { + return ObjectCloneSnippets.arrayCloneMethod; + } else if (type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) { + // arrays are assignable to Object, Cloneable and Serializable + return ObjectCloneSnippets.genericCloneMethod; + } else { + return ObjectCloneSnippets.instanceCloneMethod; + } + } + + @Override + public void lower(LoweringTool tool) { + if (!GraalOptions.IntrinsifyObjectClone) { + super.lower(tool); + return; + } + ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(selectSnippetMethod(tool)); + if (Debug.isLogEnabled()) { + Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); + } + + StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); + assert snippetGraph != null : "ObjectCloneSnippets should be installed"; + InvokeNode invoke = replaceWithInvoke(); + InliningUtil.inline(invoke, snippetGraph, false); + } + + private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type); + } + + private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) { + if (stamp.isExactType()) { + return stamp.type(); + } else { + ResolvedJavaType type = stamp.type().findUniqueConcreteSubtype(); + if (type != null) { + assumptions.recordConcreteSubtype(stamp.type(), type); + } + return type; + } + } + + @Override + public void virtualize(VirtualizerTool tool) { + State originalState = tool.getObjectState(getObject()); + if (originalState != null && originalState.getState() == EscapeState.Virtual) { + VirtualObjectNode originalVirtual = originalState.getVirtualObject(); + if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) { + ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()]; + for (int i = 0; i < newEntryState.length; i++) { + newEntryState[i] = originalState.getEntry(i); + } + VirtualObjectNode newVirtual = originalVirtual.duplicate(); + tool.createVirtualObject(newVirtual, newEntryState, 0); + tool.replaceWithVirtual(newVirtual); + } + } else { + ValueNode obj; + if (originalState != null) { + obj = originalState.getMaterializedValue(); + } else { + obj = tool.getReplacedValue(getObject()); + } + ResolvedJavaType type = getConcreteType(obj.objectStamp(), tool.getAssumptions()); + if (isCloneableType(type, tool.getMetaAccessProvider())) { + if (!type.isArray()) { + ResolvedJavaField[] fields = type.getInstanceFields(true); + ValueNode[] state = new ValueNode[fields.length]; + final LoadFieldNode[] loads = new LoadFieldNode[fields.length]; + for (int i = 0; i < fields.length; i++) { + state[i] = loads[i] = graph().add(new LoadFieldNode(obj, fields[i])); + } + + VirtualObjectNode newVirtual = new VirtualInstanceNode(type, fields); + final StructuredGraph structuredGraph = (StructuredGraph) graph(); + tool.customAction(new Runnable() { + + public void run() { + for (LoadFieldNode load : loads) { + structuredGraph.addBeforeFixed(ObjectCloneNode.this, load); + } + } + }); + tool.createVirtualObject(newVirtual, state, 0); + tool.replaceWithVirtual(newVirtual); + } + } + } + } + + @Override + public ValueNode length() { + if (getObject() instanceof ArrayLengthProvider) { + return ((ArrayLengthProvider) getObject()).length(); + } else { + return null; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java Mon Feb 11 10:46:48 2013 +0100 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, 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.snippets; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; + +public class ObjectCloneSnippets implements SnippetsInterface { + + public static final Method instanceCloneMethod = getCloneMethod("instanceClone"); + public static final Method arrayCloneMethod = getCloneMethod("arrayClone"); + public static final Method genericCloneMethod = getCloneMethod("genericClone"); + + private static Method getCloneMethod(String name) { + try { + return ObjectCloneSnippets.class.getDeclaredMethod(name, Object.class); + } catch (SecurityException | NoSuchMethodException e) { + throw new GraalInternalError(e); + } + } + + private static Object instanceClone(Object src, Word hub, int layoutHelper) { + int instanceSize = layoutHelper; + Pointer memory = NewObjectSnippets.allocate(instanceSize); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); + Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false); + + memory = Word.fromObject(result); + for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) { + memory.writeWord(offset, Word.fromObject(src).readWord(offset)); + } + + return result; + } + + private static Object arrayClone(Object src, Word hub, int layoutHelper) { + int arrayLength = ArrayLengthNode.arrayLength(src); + int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); + int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); + int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize); + + Pointer memory = NewObjectSnippets.allocate(sizeInBytes); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); + Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false); + + memory = Word.fromObject(result); + for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { + memory.writeWord(offset, Word.fromObject(src).readWord(offset)); + } + return result; + } + + private static Word getAndCheckHub(Object src) { + Word hub = loadHub(src); + if (!(src instanceof Cloneable)) { + probability(DEOPT_PATH_PROBABILITY); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + return hub; + } + + @Snippet + public static Object instanceClone(Object src) { + instanceCloneCounter.inc(); + Word hub = getAndCheckHub(src); + return instanceClone(src, hub, hub.readInt(layoutHelperOffset())); + } + + @Snippet + public static Object arrayClone(Object src) { + arrayCloneCounter.inc(); + Word hub = getAndCheckHub(src); + int layoutHelper = hub.readInt(layoutHelperOffset()); + return arrayClone(src, hub, layoutHelper); + } + + @Snippet + public static Object genericClone(Object src) { + genericCloneCounter.inc(); + Word hub = getAndCheckHub(src); + int layoutHelper = hub.readInt(layoutHelperOffset()); + if (layoutHelper < 0) { + probability(LIKELY_PROBABILITY); + genericArrayCloneCounter.inc(); + return arrayClone(src, hub, layoutHelper); + } else { + genericInstanceCloneCounter.inc(); + return instanceClone(src, hub, layoutHelper); + } + } + + private static final SnippetCounter.Group cloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone") : null; + private static final SnippetCounter instanceCloneCounter = new SnippetCounter(cloneCounters, "instanceClone", "clone snippet for instances"); + private static final SnippetCounter arrayCloneCounter = new SnippetCounter(cloneCounters, "arrayClone", "clone snippet for arrays"); + private static final SnippetCounter genericCloneCounter = new SnippetCounter(cloneCounters, "genericClone", "clone snippet for arrays and instances"); + + private static final SnippetCounter.Group genericCloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone generic snippet") : null; + private static final SnippetCounter genericInstanceCloneCounter = new SnippetCounter(genericCloneCounters, "genericInstanceClone", "generic clone implementation took instance path"); + private static final SnippetCounter genericArrayCloneCounter = new SnippetCounter(genericCloneCounters, "genericArrayClone", "generic clone implementation took array path"); + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java Mon Feb 11 10:46:48 2013 +0100 @@ -26,7 +26,7 @@ import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.ClassSubstitution.*; import com.oracle.graal.word.*; /** @@ -45,4 +45,7 @@ public static int hashCode(final Object thisObj) { return computeHashCode(thisObj); } + + @MacroSubstitution(macro = ObjectCloneNode.class, isStatic = false) + public static native Object clone(Object obj); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java Mon Feb 11 10:46:48 2013 +0100 @@ -42,7 +42,7 @@ public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class); public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class); - @MacroSubstitution(macro = ArrayCopyNode.class, isStatic = true) + @MacroSubstitution(macro = ArrayCopyNode.class) public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); @MethodSubstitution
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Feb 11 10:46:48 2013 +0100 @@ -642,14 +642,14 @@ private JavaMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); - assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()); + assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; return result; } private JavaField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()); + assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Mon Feb 11 10:46:48 2013 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.asm.*; -//@formatter:off public class AMD64TestOp extends AMD64LIRInstruction { @Use({REG}) protected Value x; @@ -55,21 +54,36 @@ public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value x, Value y) { if (isRegister(y)) { switch (x.getKind()) { - case Int: masm.testl(asIntReg(x), asIntReg(y)); break; - case Long: masm.testq(asLongReg(x), asLongReg(y)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Int: + masm.testl(asIntReg(x), asIntReg(y)); + break; + case Long: + masm.testq(asLongReg(x), asLongReg(y)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else if (isConstant(y)) { switch (x.getKind()) { - case Int: masm.testl(asIntReg(x), tasm.asIntConst(y)); break; - case Long: masm.testq(asLongReg(x), tasm.asIntConst(y)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Int: + masm.testl(asIntReg(x), tasm.asIntConst(y)); + break; + case Long: + masm.testq(asLongReg(x), tasm.asIntConst(y)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else { switch (x.getKind()) { - case Int: masm.testl(asIntReg(x), tasm.asIntAddr(y)); break; - case Long: masm.testq(asLongReg(x), tasm.asLongAddr(y)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Int: + masm.testl(asIntReg(x), tasm.asIntAddr(y)); + break; + case Long: + masm.testq(asLongReg(x), tasm.asLongAddr(y)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -26,6 +26,11 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +/** + * This node will perform a "test" operation on its arguments. Its result is equivalent to the + * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in + * both x and y. + */ public class IntegerTestNode extends BooleanNode implements Canonicalizable, LIRLowerable { @Input private ValueNode x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -47,8 +47,9 @@ public ValueNode canonical(CanonicalizerTool tool) { if (array() instanceof ArrayLengthProvider) { ValueNode length = ((ArrayLengthProvider) array()).length(); - assert length != null; - return length; + if (length != null) { + return length; + } } MetaAccessProvider runtime = tool.runtime(); if (runtime != null && array().isConstant() && !array().isNullConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArrayLengthProvider.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArrayLengthProvider.java Mon Feb 11 10:46:48 2013 +0100 @@ -26,5 +26,8 @@ public interface ArrayLengthProvider { + /** + * @return the length of the array described by this node, or null if it is not available + */ ValueNode length(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Mon Feb 11 10:46:48 2013 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -43,6 +44,12 @@ MetaAccessProvider getMetaAccessProvider(); /** + * @return the {@link Assumptions} associated with the current compilation, which can be used to + * make type assumptions during virtualization. + */ + Assumptions getAssumptions(); + + /** * This method should be used to query the maximum size of virtualized objects before attempting * virtualization. *
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -70,4 +70,9 @@ public Kind entryKind(int index) { return kind; } + + @Override + public BoxedVirtualObjectNode duplicate() { + return new BoxedVirtualObjectNode(type, kind, unboxedValue); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -132,4 +132,9 @@ assert index >= 0 && index < length; return componentType.getKind(); } + + @Override + public VirtualArrayNode duplicate() { + return new VirtualArrayNode(componentType, length); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -32,16 +32,23 @@ private final ResolvedJavaType type; private final ResolvedJavaField[] fields; - private final HashMap<ResolvedJavaField, Integer> fieldMap = new HashMap<>(); + private final HashMap<ResolvedJavaField, Integer> fieldMap; public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { this.type = type; this.fields = fields; + fieldMap = new HashMap<>(); for (int i = 0; i < fields.length; i++) { fieldMap.put(fields[i], i); } } + private VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, HashMap<ResolvedJavaField, Integer> fieldMap) { + this.type = type; + this.fields = fields; + this.fieldMap = fieldMap; + } + @Override public ResolvedJavaType type() { return type; @@ -85,4 +92,9 @@ assert index >= 0 && index < fields.length; return fields[index].getKind(); } + + @Override + public VirtualInstanceNode duplicate() { + return new VirtualInstanceNode(type, fields, fieldMap); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -53,4 +53,6 @@ public abstract int entryIndexForOffset(long constantOffset); public abstract Kind entryKind(int index); + + public abstract VirtualObjectNode duplicate(); }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Feb 11 10:46:48 2013 +0100 @@ -197,6 +197,7 @@ public static boolean OptDevirtualizeInvokesOptimistically = true; // Intrinsification settings + public static boolean IntrinsifyObjectClone = true; public static boolean IntrinsifyArrayCopy = true; public static boolean IntrinsifyObjectMethods = true; public static boolean IntrinsifySystemMethods = true;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java Mon Feb 11 10:46:48 2013 +0100 @@ -313,37 +313,37 @@ @MethodSubstitution(isStatic = false) public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Byte); } @MethodSubstitution(isStatic = false) public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Short); } @MethodSubstitution(isStatic = false) public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Char); } @MethodSubstitution(isStatic = false) public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Int); } @MethodSubstitution(isStatic = false) public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Long); } @MethodSubstitution(isStatic = false) public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Float); } @MethodSubstitution(isStatic = false) public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { - DirectStoreNode.store(address, value); + DirectStoreNode.store(address, value, Kind.Double); } @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java Mon Feb 11 10:46:48 2013 +0100 @@ -37,40 +37,48 @@ @Input private ValueNode address; @Input private ValueNode value; + private final Kind kind; - public DirectStoreNode(ValueNode address, ValueNode value) { + public DirectStoreNode(ValueNode address, ValueNode value, Kind kind) { super(StampFactory.forVoid()); this.address = address; this.value = value; + this.kind = kind; } - @NodeIntrinsic - public static native void store(long address, boolean value); - - @NodeIntrinsic - public static native void store(long address, byte value); - - @NodeIntrinsic - public static native void store(long address, short value); - - @NodeIntrinsic - public static native void store(long address, char value); - - @NodeIntrinsic - public static native void store(long address, int value); - - @NodeIntrinsic - public static native void store(long address, long value); - - @NodeIntrinsic - public static native void store(long address, float value); - - @NodeIntrinsic - public static native void store(long address, double value); - @Override public void generate(LIRGeneratorTool gen) { Value v = gen.operand(value); - gen.emitStore(new Address(v.getKind(), gen.operand(address)), v, false); + gen.emitStore(new Address(kind, gen.operand(address)), v, false); } + + /* + * The kind of the store is provided explicitly in these intrinsics because it is not always + * possible to determine the kind from the given value during compilation (because stack kinds + * are used). + */ + + @NodeIntrinsic + public static native void store(long address, boolean value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, byte value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, short value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, char value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, int value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, long value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, float value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native void store(long address, double value, @ConstantNodeParameter Kind kind); }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Feb 11 10:46:48 2013 +0100 @@ -92,7 +92,7 @@ public Boolean call() { SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); - PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime); + PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions); ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); if (closure.getNewVirtualObjectCount() == 0) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Feb 11 10:46:48 2013 +0100 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -59,10 +60,10 @@ private final VirtualizerToolImpl tool; - public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess) { + public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) { this.usages = usages; this.schedule = schedule; - tool = new VirtualizerToolImpl(effects, usages, metaAccess); + tool = new VirtualizerToolImpl(effects, usages, metaAccess, assumptions); } public GraphEffectList getEffects() {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri Feb 08 18:05:40 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Feb 11 10:46:48 2013 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -38,11 +39,13 @@ private final GraphEffectList effects; private final NodeBitMap usages; private final MetaAccessProvider metaAccess; + private final Assumptions assumptions; - VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess) { + VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) { this.effects = effects; this.usages = usages; this.metaAccess = metaAccess; + this.assumptions = assumptions; } private boolean deleted; @@ -56,6 +59,11 @@ return metaAccess; } + @Override + public Assumptions getAssumptions() { + return assumptions; + } + public void reset(BlockState newState, ValueNode newCurrent) { deleted = false; customAction = false;
--- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Feb 08 18:05:40 2013 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Feb 11 10:46:48 2013 +0100 @@ -701,6 +701,8 @@ set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); + // this filters out the bit that differentiates a type array from an object array + set_int("layoutHelperElementTypePrimitiveInPlace", (Klass::_lh_array_tag_type_value & ~Klass::_lh_array_tag_obj_value) << Klass::_lh_array_tag_shift); set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset()));