Mercurial > hg > graal-jvmci-8
changeset 11876:acfff1de2aa7
Merge
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Wed, 02 Oct 2013 17:34:27 +0200 |
parents | 35bdfb9ac12f (diff) 18824519c172 (current diff) |
children | ef895852aeb4 |
files | |
diffstat | 14 files changed, 250 insertions(+), 156 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Oct 02 17:34:27 2013 +0200 @@ -86,7 +86,7 @@ */ @Option(help = "Pattern for method(s) to which intrinsification will not be applied. " + "See MethodFilter class for pattern syntax.") - public static final OptionValue<String> IntrinsificationsDisabled = new OptionValue<>("Object.clone"); + public static final OptionValue<String> IntrinsificationsDisabled = new OptionValue<>(null); // @formatter:on }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Oct 02 17:34:27 2013 +0200 @@ -44,6 +44,19 @@ import com.oracle.graal.options.*; import com.oracle.graal.replacements.nodes.*; +/** + * This class contains infrastructure to maintain counters based on {@link DynamicCounterNode}s. The + * infrastructure is enabled by specifying either the GenericDynamicCounters or + * BenchmarkDynamicCounters option.<br/> + * + * The counters are kept in a special area in the native JavaThread object, and the number of + * counters is configured in {@code thread.hpp (GRAAL_COUNTERS_SIZE)}. This file also contains an + * option to exclude compiler threads ({@code GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS}, which + * defaults to true). + * + * The subsystems that use the logging need to have their own options to turn on the counters, and + * insert DynamicCounterNodes when they're enabled. + */ public class BenchmarkCounters { static class Options {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Oct 02 17:34:27 2013 +0200 @@ -40,14 +40,17 @@ import com.oracle.graal.graph.iterators.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; @@ -63,6 +66,22 @@ */ public class MonitorSnippets implements Snippets { + public static class Options { + + //@formatter:off + @Option(help = "") + private static final OptionValue<Boolean> ProfileMonitors = new OptionValue<>(false); + //@formatter:on + } + + private static final boolean PROFILE_CONTEXT = false; + + @Fold + @SuppressWarnings("unused") + private static boolean doProfile(String path) { + return Options.ProfileMonitors.getValue(); + } + /** * Monitor operations on objects whose type contains this substring will be traced. */ @@ -118,7 +137,7 @@ trace(trace, " tmp: 0x%016lx\n", tmp); if (probability(FREQUENT_PROBABILITY, tmp.equal(0))) { // Object is already biased to current thread -> done - traceObject(trace, "+lock{bias:existing}", object); + traceObject(trace, "+lock{bias:existing}", object, true); return; } @@ -154,13 +173,13 @@ trace(trace, " biasedMark: 0x%016lx\n", biasedMark); if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) { // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:acquired}", object); + traceObject(trace, "+lock{bias:acquired}", object, true); return; } // If the biasing toward our thread failed, this means that another thread // owns the bias and we need to revoke that bias. The revocation will occur // in the interpreter runtime. - traceObject(trace, "+lock{stub:revoke}", object); + traceObject(trace, "+lock{stub:revoke}", object, true); monitorenterStub(MONITORENTER, object, lock); return; } else { @@ -174,13 +193,13 @@ trace(trace, " biasedMark: 0x%016lx\n", biasedMark); if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) { // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:transfer}", object); + traceObject(trace, "+lock{bias:transfer}", object, true); return; } // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. - traceObject(trace, "+lock{stub:epoch-expired}", object); + traceObject(trace, "+lock{stub:epoch-expired}", object, true); monitorenterStub(MONITORENTER, object, lock); return; } @@ -237,16 +256,16 @@ final Word stackPointer = stackPointer(); if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { // Most likely not a recursive lock, go into a slow runtime call - traceObject(trace, "+lock{stub:failed-cas}", object); + traceObject(trace, "+lock{stub:failed-cas}", object, true); monitorenterStub(MONITORENTER, object, lock); return; } else { // Recursively locked => write 0 to the lock slot lock.writeWord(lockDisplacedMarkOffset(), Word.zero(), DISPLACED_MARK_WORD_LOCATION); - traceObject(trace, "+lock{recursive}", object); + traceObject(trace, "+lock{recursive}", object, true); } } else { - traceObject(trace, "+lock{cas}", object); + traceObject(trace, "+lock{cas}", object, true); } } @@ -263,7 +282,7 @@ // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above final Word lock = beginLockScope(lockDepth); - traceObject(trace, "+lock{stub}", object); + traceObject(trace, "+lock{stub}", object, true); monitorenterStub(MONITORENTER, object, lock); } @@ -282,7 +301,7 @@ if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern())))) { endLockScope(); decCounter(); - traceObject(trace, "-lock{bias}", object); + traceObject(trace, "-lock{bias}", object, false); return; } } @@ -295,7 +314,7 @@ if (displacedMark.equal(0)) { // Recursive locking => done - traceObject(trace, "-lock{recursive}", object); + traceObject(trace, "-lock{recursive}", object, false); } else { verifyOop(object); // Test if object's mark word is pointing to the displaced mark word, and if so, restore @@ -304,10 +323,10 @@ if (probability(VERY_SLOW_PATH_PROBABILITY, DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) { // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. - traceObject(trace, "-lock{stub}", object); + traceObject(trace, "-lock{stub}", object, false); MonitorExitStubCall.call(object, lockDepth); } else { - traceObject(trace, "-lock{cas}", object); + traceObject(trace, "-lock{cas}", object, false); } } endLockScope(); @@ -320,13 +339,16 @@ @Snippet public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { verifyOop(object); - traceObject(trace, "-lock{stub}", object); + traceObject(trace, "-lock{stub}", object, false); MonitorExitStubCall.call(object, lockDepth); endLockScope(); decCounter(); } - private static void traceObject(boolean enabled, String action, Object object) { + private static void traceObject(boolean enabled, String action, Object object, boolean enter) { + if (doProfile(action)) { + DynamicCounterNode.counter(action, enter ? "~monitorenter" : "~monitorexit", 1, PROFILE_CONTEXT); + } if (enabled) { Log.print(action); Log.print(' ');
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Oct 02 17:34:27 2013 +0200 @@ -34,17 +34,21 @@ 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.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; @@ -59,6 +63,20 @@ public static final LocationIdentity INIT_LOCATION = new NamedLocationIdentity("Initialization"); + public static class Options { + + //@formatter:off + @Option(help = "") + private static final OptionValue<Boolean> ProfileAllocations = new OptionValue<>(false); + //@formatter:on + } + + static enum ProfileMode { + AllocatingMethods, InstanceOrArray, AllocatedTypes, AllocatedTypesInMethods, Total + } + + public static final ProfileMode PROFILE_MODE = ProfileMode.Total; + @Snippet public static Word allocate(int size) { Word thread = thread(); @@ -76,8 +94,41 @@ return Word.zero(); } + @Fold + private static String createName(String path, String typeContext) { + switch (PROFILE_MODE) { + case AllocatingMethods: + return ""; + case InstanceOrArray: + return path; + case AllocatedTypes: + case AllocatedTypesInMethods: + return typeContext; + case Total: + return "bytes"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Fold + @SuppressWarnings("unused") + private static boolean doProfile(String path, String typeContext) { + return Options.ProfileAllocations.getValue(); + } + + private static void profileAllocation(String path, long size, String typeContext) { + if (doProfile(path, typeContext)) { + String name = createName(path, typeContext); + + boolean context = PROFILE_MODE == ProfileMode.AllocatingMethods || PROFILE_MODE == ProfileMode.AllocatedTypesInMethods; + DynamicCounterNode.counter(name, "~bytes", size, context); + DynamicCounterNode.counter(name, "~sites", 1, context); + } + } + @Snippet - public static Object allocateInstance(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents) { + public static Object allocateInstance(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter String typeContext) { Object result; Word thread = thread(); Word top = readTlabTop(thread); @@ -90,6 +141,7 @@ new_stub.inc(); result = NewInstanceStubCall.call(hub); } + profileAllocation("instance", size, typeContext); return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); } @@ -99,15 +151,16 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArray(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, @ConstantParameter boolean fillContents) { + public static Object allocateArray(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter String typeContext) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents); + return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, typeContext); } - private static Object allocateArrayImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents) { + private static Object allocateArrayImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, String typeContext) { Object result; int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); @@ -123,6 +176,7 @@ newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } + profileAllocation("array", allocationSize, typeContext); return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); } @@ -156,7 +210,7 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents); + return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, "dynamic type"); } /** @@ -261,6 +315,7 @@ args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); args.addConst("fillContents", newInstanceNode.fillContents()); + args.addConst("typeContext", MetaUtil.toJavaName(type, false)); SnippetTemplate template = template(args); Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); @@ -286,6 +341,7 @@ args.addConst("headerSize", headerSize); args.addConst("log2ElementSize", log2ElementSize); args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("typeContext", MetaUtil.toJavaName(arrayType, false)); SnippetTemplate template = template(args); Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Wed Oct 02 17:34:27 2013 +0200 @@ -59,49 +59,72 @@ } ResolvedJavaType type = ObjectStamp.typeOrNull(getObject()); - Method method; - /* - * The first condition tests if the parameter is an array, the second condition tests if the - * parameter can be an array. Otherwise, the parameter is known to be a non-array object. - */ - if (type.isArray()) { - method = ObjectCloneSnippets.arrayCloneMethod; - } else if (type == null || type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) { - method = ObjectCloneSnippets.genericCloneMethod; - } else { - method = ObjectCloneSnippets.instanceCloneMethod; + if (type != null) { + if (type.isArray()) { + Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getKind()); + if (method != null) { + final ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method); + final Replacements replacements = tool.getReplacements(); + StructuredGraph snippetGraph = Debug.scope("ArrayCopySnippet", snippetMethod, new Callable<StructuredGraph>() { + + @Override + public StructuredGraph call() throws Exception { + return replacements.getSnippet(snippetMethod); + } + }); + + assert snippetGraph != null : "ObjectCloneSnippets should be installed"; + return lowerReplacement(snippetGraph.copy(), tool); + } + } else { + type = getConcreteType(getObject().stamp(), tool.assumptions(), tool.getRuntime()); + if (type != null) { + StructuredGraph newGraph = new StructuredGraph(); + LocalNode local = newGraph.add(new LocalNode(0, getObject().stamp())); + NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); + newGraph.addAfterFixed(newGraph.start(), newInstance); + ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance)); + newGraph.addAfterFixed(newInstance, returnNode); + + for (ResolvedJavaField field : type.getInstanceFields(true)) { + LoadFieldNode load = newGraph.add(new LoadFieldNode(local, field)); + newGraph.addBeforeFixed(returnNode, load); + newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); + } + return lowerReplacement(newGraph, tool); + } + } } - final ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method); - final Replacements replacements = tool.getReplacements(); - StructuredGraph snippetGraph = Debug.scope("ArrayCopySnippet", snippetMethod, new Callable<StructuredGraph>() { - - @Override - public StructuredGraph call() throws Exception { - return replacements.getSnippet(snippetMethod); - } - }); - - assert snippetGraph != null : "ObjectCloneSnippets should be installed"; - return lowerReplacement(snippetGraph.copy(), tool); + return null; } private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { - return type != null && metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type); + return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type); } - private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions) { + /* + * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an + * exact type) and if it is a cloneable type. + * + * If yes, then the exact type is returned, otherwise it returns null. + */ + private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { if (!(stamp instanceof ObjectStamp)) { return null; } ObjectStamp objectStamp = (ObjectStamp) stamp; - if (objectStamp.isExactType() || objectStamp.type() == null) { - return objectStamp.type(); + if (objectStamp.type() == null) { + return null; + } else if (objectStamp.isExactType()) { + return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null; } else { ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype(); - if (type != null) { + if (type != null && isCloneableType(type, metaAccess)) { assumptions.recordConcreteSubtype(objectStamp.type(), type); + return type; + } else { + return null; } - return type; } } @@ -126,21 +149,19 @@ } else { obj = tool.getReplacedValue(getObject()); } - ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions()); - if (isCloneableType(type, tool.getMetaAccessProvider())) { - if (!type.isArray()) { - VirtualInstanceNode newVirtual = new VirtualInstanceNode(type, true); - ResolvedJavaField[] fields = newVirtual.getFields(); + ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider()); + if (type != null && !type.isArray()) { + VirtualInstanceNode newVirtual = new VirtualInstanceNode(type, true); + ResolvedJavaField[] fields = newVirtual.getFields(); - 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] = new LoadFieldNode(obj, fields[i]); - tool.addNode(loads[i]); - } - tool.createVirtualObject(newVirtual, state, null); - tool.replaceWithVirtual(newVirtual); + 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] = new LoadFieldNode(obj, fields[i]); + tool.addNode(loads[i]); } + tool.createVirtualObject(newVirtual, state, null); + tool.replaceWithVirtual(newVirtual); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Oct 02 17:34:27 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -22,113 +22,77 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.api.meta.LocationIdentity.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; - import java.lang.reflect.*; +import java.util.*; 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.replacements.*; -import com.oracle.graal.word.*; public class ObjectCloneSnippets implements Snippets { - public static final Method instanceCloneMethod = getCloneMethod("instanceClone"); - public static final Method arrayCloneMethod = getCloneMethod("arrayClone"); - public static final Method genericCloneMethod = getCloneMethod("genericClone"); + public static final EnumMap<Kind, Method> arrayCloneMethods = new EnumMap<>(Kind.class); - private static Method getCloneMethod(String name) { + static { + arrayCloneMethods.put(Kind.Byte, getCloneMethod("byteArrayClone", byte[].class)); + arrayCloneMethods.put(Kind.Char, getCloneMethod("charArrayClone", char[].class)); + arrayCloneMethods.put(Kind.Int, getCloneMethod("intArrayClone", int[].class)); + arrayCloneMethods.put(Kind.Long, getCloneMethod("longArrayClone", long[].class)); + arrayCloneMethods.put(Kind.Object, getCloneMethod("objectArrayClone", Object[].class)); + } + + private static Method getCloneMethod(String name, Class<?> param) { try { - return ObjectCloneSnippets.class.getDeclaredMethod(name, Object.class); + return ObjectCloneSnippets.class.getDeclaredMethod(name, param); } catch (SecurityException | NoSuchMethodException e) { throw new GraalInternalError(e); } } - private static Object instanceClone(Object src, Word hub, int layoutHelper) { - int instanceSize = layoutHelper; - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false); - - for (int offset = instanceHeaderSize(); offset < instanceSize; offset += wordSize()) { - /* - * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values - * to be copied atomically, but here they are copied as two 4-byte word values. - */ - ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); + @Snippet(removeAllFrameStates = true) + public static byte[] byteArrayClone(byte[] src) { + byte[] result = new byte[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; } - 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); - - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false); - - for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { - /* - * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values - * to be copied atomically, but here they are copied as two 4-byte word values. - */ - ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); + @Snippet(removeAllFrameStates = true) + public static char[] charArrayClone(char[] src) { + char[] result = new char[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; } return result; } - private static Word getAndCheckHub(Object src) { - Word hub = loadHub(src); - if (!(src instanceof Cloneable)) { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + @Snippet(removeAllFrameStates = true) + public static int[] intArrayClone(int[] src) { + int[] result = new int[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; } - return hub; - } - - @Snippet - public static Object instanceClone(Object src) { - instanceCloneCounter.inc(); - Word hub = getAndCheckHub(src); - return instanceClone(src, hub, hub.readInt(layoutHelperOffset(), FINAL_LOCATION)); - } - - @Snippet - public static Object arrayClone(Object src) { - arrayCloneCounter.inc(); - Word hub = getAndCheckHub(src); - int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); - return arrayClone(src, hub, layoutHelper); + return result; } - @Snippet - public static Object genericClone(Object src) { - genericCloneCounter.inc(); - Word hub = getAndCheckHub(src); - int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); - if (probability(LIKELY_PROBABILITY, layoutHelper < 0)) { - genericArrayCloneCounter.inc(); - return arrayClone(src, hub, layoutHelper); - } else { - genericInstanceCloneCounter.inc(); - return instanceClone(src, hub, layoutHelper); + @Snippet(removeAllFrameStates = true) + public static long[] longArrayClone(long[] src) { + long[] result = new long[src.length]; + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; } + return result; } - private static final SnippetCounter.Group cloneCounters = SnippetCounters.getValue() ? 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 = SnippetCounters.getValue() ? 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"); - + @Snippet(removeAllFrameStates = true) + public static Object[] objectArrayClone(Object[] src) { + Object[] result = (Object[]) DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length); + for (int i = 0; i < result.length; i++) { + result[i] = src[i]; + } + return result; + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Oct 02 17:34:27 2013 +0200 @@ -305,7 +305,7 @@ private void inline(InvokeNode invoke) { ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(runtime, new Assumptions(false), runtime.getTarget()); - StructuredGraph calleeGraph = repl.makeGraph(method, null, null); + StructuredGraph calleeGraph = repl.makeGraph(method, null, null, false); InliningUtil.inline(invoke, calleeGraph, false); } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Oct 02 17:34:27 2013 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.tiers.*; @@ -172,6 +173,9 @@ int fixedCount = 0; while (fixed instanceof FixedWithNextNode) { fixed = ((FixedWithNextNode) fixed).next(); + if (fixed instanceof CommitAllocationNode) { + return false; + } fixedCount++; } if (fixedCount > 1) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Oct 02 17:34:27 2013 +0200 @@ -70,8 +70,6 @@ @Option(help = "") public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true); @Option(help = "") - public static final OptionValue<Boolean> EscapeAnalysisHistogram = new OptionValue<>(false); - @Option(help = "") public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2); @Option(help = "") public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Oct 02 17:34:27 2013 +0200 @@ -57,7 +57,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); } @Test
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Oct 02 17:34:27 2013 +0200 @@ -61,7 +61,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); } @Test
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Wed Oct 02 17:34:27 2013 +0200 @@ -51,7 +51,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); } @LongTest
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Oct 02 17:34:27 2013 +0200 @@ -84,7 +84,7 @@ StructuredGraph graph = graphs.get(method); if (graph == null) { - graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method))); + graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method), method.getAnnotation(Snippet.class).removeAllFrameStates())); graph = graphs.get(method); } return graph; @@ -97,7 +97,7 @@ } StructuredGraph graph = graphs.get(substitute); if (graph == null) { - graphs.putIfAbsent(substitute, makeGraph(substitute, original, inliningPolicy(substitute))); + graphs.putIfAbsent(substitute, makeGraph(substitute, original, inliningPolicy(substitute), false)); graph = graphs.get(substitute); } return graph; @@ -221,9 +221,10 @@ * @param original the original method if {@code method} is a {@linkplain MethodSubstitution * substitution} otherwise null * @param policy the inlining policy to use during preprocessing + * @param removeAllFrameStates removes all frame states from side effecting instructions */ - public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, SnippetInliningPolicy policy) { - return createGraphMaker(method, original).makeGraph(policy); + public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, SnippetInliningPolicy policy, boolean removeAllFrameStates) { + return createGraphMaker(method, original).makeGraph(policy, removeAllFrameStates); } /** @@ -261,7 +262,7 @@ this.original = original; } - public StructuredGraph makeGraph(final SnippetInliningPolicy policy) { + public StructuredGraph makeGraph(final SnippetInliningPolicy policy, final boolean removeAllFrameStates) { return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() { @Override @@ -271,7 +272,7 @@ // Cannot have a finalized version of a graph in the cache graph = graph.copy(); - finalizeGraph(graph); + finalizeGraph(graph, removeAllFrameStates); Debug.dump(graph, "%s: Final", method.getName()); @@ -283,7 +284,7 @@ /** * Does final processing of a snippet graph. */ - protected void finalizeGraph(StructuredGraph graph) { + protected void finalizeGraph(StructuredGraph graph, boolean removeAllFrameStates) { new NodeIntrinsificationPhase(runtime).apply(graph); if (!SnippetTemplate.hasConstantParameter(method)) { NodeIntrinsificationVerificationPhase.verify(graph); @@ -291,7 +292,15 @@ new ConvertDeoptimizeToGuardPhase().apply(graph); if (original == null) { - new SnippetFrameStateCleanupPhase().apply(graph); + if (removeAllFrameStates) { + for (Node node : graph.getNodes()) { + if (node instanceof StateSplit) { + ((StateSplit) node).setStateAfter(null); + } + } + } else { + new SnippetFrameStateCleanupPhase().apply(graph); + } } new DeadCodeEliminationPhase().apply(graph); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Wed Oct 02 15:37:06 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Wed Oct 02 17:34:27 2013 +0200 @@ -45,6 +45,13 @@ Class<? extends SnippetInliningPolicy> inlining() default SnippetInliningPolicy.class; /** + * Specifies whether all FrameStates within this snippet should always be removed. If this is + * false, FrameStates are only removed if there are no side-effecting instructions in the + * snippet. + */ + boolean removeAllFrameStates() default false; + + /** * Guides inlining decisions used when installing a snippet. */ public interface SnippetInliningPolicy {