# HG changeset patch # User Stefan Anzinger # Date 1434015355 -7200 # Node ID 0ab08be12bbbefe55710a6a9da2b9dfef06823fe # Parent 0df6a0cb4b5f4677124a645bd34bb278d4cb890f# Parent 9fed54b2b98f827df1620d63dd98d89a07b8ec74 Merge diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotAddressLowering.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotAddressLowering.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotAddressLowering.java Thu Jun 11 11:35:55 2015 +0200 @@ -102,9 +102,10 @@ ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); addr.setBase(base); } else if (encoding.base != 0) { - long disp = addr.getDisplacement() + heapBase; + long disp = addr.getDisplacement() + encoding.base; if (NumUtil.isInt(disp)) { addr.setDisplacement((int) disp); + addr.setBase(null); } else { return false; } diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Thu Jun 11 11:35:55 2015 +0200 @@ -23,16 +23,21 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*; import static com.oracle.jvmci.code.CallingConvention.Type.*; import static com.oracle.jvmci.code.CodeUtil.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; +import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.OptimisticOptimizations.Optimization; import com.oracle.graal.phases.tiers.*; @@ -50,9 +55,12 @@ HotSpotProviders providers = HotSpotGraalRuntime.runtime().getHostProviders(); final boolean isOSR = entryBCI != INVOCATION_ENTRY_BCI; - StructuredGraph graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue())); - if (!mustRecordMethodInlining) { - graph.disableInlinedMethodRecording(); + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers); + if (graph == null) { + graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue())); + if (!mustRecordMethodInlining) { + graph.disableInlinedMethodRecording(); + } } CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); @@ -85,6 +93,29 @@ return result; } + /** + * Gets a graph produced from the intrinsic for a given method that can be compiled and + * installed for the method. + * + * @param method + * @return an intrinsic graph that can be compiled and installed for {@code method} or null + */ + protected StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers) { + Replacements replacements = providers.getReplacements(); + ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method); + if (substMethod != null) { + assert !substMethod.equals(method); + StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES); + Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); + IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, ROOT_COMPILATION); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); + assert !graph.isFrozen(); + return graph; + } + return null; + } + protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { return new OptimisticOptimizations(profilingInfo); } diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Thu Jun 11 11:35:55 2015 +0200 @@ -118,6 +118,8 @@ for (Node successor : successors()) { if (successor != survivingSuccessor) { tool.deleteBranch(successor); + // deleteBranch can change the successors so reload it + survivingSuccessor = successorAtKey(constant); } } tool.addToWorkList(survivingSuccessor); diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Thu Jun 11 11:35:55 2015 +0200 @@ -80,6 +80,13 @@ StructuredGraph getSubstitution(ResolvedJavaMethod method, boolean fromBytecodeOnly, int invokeBci); /** + * Gets a method that is a substitution for a given method. + * + * @return the method, if any, whose bytecode are a substitution for {@code method} + */ + ResolvedJavaMethod getSubstitutionMethod(ResolvedJavaMethod method); + + /** * Determines if there is a {@linkplain #getSubstitution(ResolvedJavaMethod, int) substitution * graph} for a given method. * diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Jun 11 11:35:55 2015 +0200 @@ -100,7 +100,7 @@ if (!method.equals(curMethod) || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); - TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile); + TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile.getAbsolutePath()); } curMethod = method; curDecorators = decorators; @@ -131,7 +131,7 @@ } catch (FileNotFoundException e) { throw new JVMCIError("Could not open " + cfgFile.getAbsolutePath()); } - TTY.println("CFGPrinter: Output to file %s", cfgFile); + TTY.println("CFGPrinter: Output to file %s", cfgFile.getAbsolutePath()); } if (!checkMethodScope()) { diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Thu Jun 11 11:35:55 2015 +0200 @@ -183,7 +183,7 @@ } public void printMachineCode(String code, String label) { - if (code.length() == 0) { + if (code == null || code.length() == 0) { return; } if (label != null) { diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Jun 11 11:35:55 2015 +0200 @@ -327,8 +327,8 @@ if (plugin != null) { if (!plugin.inlineOnly() || invokeBci >= 0) { if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; - substitute = msplugin.getSubstitute(providers.getMetaAccess()); + MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; + substitute = msPlugin.getSubstitute(providers.getMetaAccess()); } else { StructuredGraph graph = new IntrinsicGraphBuilder(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), original, invokeBci).buildGraph(plugin); if (graph != null) { @@ -682,6 +682,11 @@ } public ResolvedJavaMethod getSubstitutionMethod(ResolvedJavaMethod original) { + InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(original); + if (plugin instanceof MethodSubstitutionPlugin) { + MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; + return msPlugin.getSubstitute(providers.getMetaAccess()); + } ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName()); return cr == null ? null : cr.methodSubstitutions.get(original); } diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Jun 11 11:35:55 2015 +0200 @@ -422,17 +422,6 @@ } } - public StructuredGraph createRootGraph(StructuredGraph graph) { - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompiler.Optimizations, null).apply(graph); - return graph; - } - - public StructuredGraph createInlineGraph(String name, StructuredGraph caller) { - StructuredGraph graph = new StructuredGraph(name, callInlinedMethod, AllowAssumptions.from(caller.getAssumptions() != null)); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompiler.Optimizations, null).apply(graph); - return graph; - } - private static void postPartialEvaluation(final StructuredGraph graph) { NeverPartOfCompilationNode.verifyNotFoundIn(graph); for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.TYPE).snapshot()) { diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java --- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Thu Jun 11 11:35:55 2015 +0200 @@ -61,16 +61,6 @@ return null; } - /** - * Called when a new property is added to a shape. - * - * @param property the added property - * @param shapeBefore shape before the property was added - * @param shapeAfter shape after the property was added - */ - public void onPropertyAdded(Property property, Shape shapeBefore, Shape shapeAfter) { - } - public ForeignAccess getForeignAccessFactory() { return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() { diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java Thu Jun 11 11:35:55 2015 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.object; + +public interface ShapeListener { + /** + * Called when a property is added, removed, or replaced. + * + * @param key identifier of the property + */ + void onPropertyTransition(Object key); +} diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java --- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java Thu Jun 11 11:35:55 2015 +0200 @@ -39,4 +39,20 @@ protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { return new ShapeBasic(layout, sharedData, parent, objectType, propertyMap, transition, allocator, id); } + + @Override + public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { + assert oldProperty.getKey().equals(newProperty.getKey()); + onPropertyTransition(oldProperty); + + Transition replacePropertyTransition = new Transition.DirectReplacePropertyTransition(oldProperty, newProperty); + ShapeImpl cachedShape = queryTransition(replacePropertyTransition); + if (cachedShape != null) { + return cachedShape; + } + PropertyMap newPropertyMap = this.getPropertyMap().replaceCopy(oldProperty, newProperty); + ShapeImpl newShape = createShape(getLayout(), getSharedData(), this, getObjectType(), newPropertyMap, replacePropertyTransition, allocator(), getId()); + addDirectTransition(replacePropertyTransition, newShape); + return newShape; + } } diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Thu Jun 11 11:35:55 2015 +0200 @@ -23,6 +23,7 @@ package com.oracle.truffle.object; import java.util.*; +import java.util.concurrent.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -39,6 +40,7 @@ import com.oracle.truffle.object.Locations.DualLocation; import com.oracle.truffle.object.Locations.ValueLocation; import com.oracle.truffle.object.Transition.AddPropertyTransition; +import com.oracle.truffle.object.Transition.DirectReplacePropertyTransition; import com.oracle.truffle.object.Transition.ObjectTypeTransition; import com.oracle.truffle.object.Transition.PropertyTransition; import com.oracle.truffle.object.Transition.RemovePropertyTransition; @@ -89,7 +91,7 @@ * @see #getTransitionMapForRead() * @see #getTransitionMapForWrite() */ - private HashMap transitionMap; + private volatile Map transitionMap; private final Transition transitionFromParent; @@ -302,8 +304,13 @@ if (transitionMap != null) { return transitionMap; } else { - invalidateLeafAssumption(); - return transitionMap = new HashMap<>(); + synchronized (getMutex()) { + if (transitionMap != null) { + return transitionMap; + } + invalidateLeafAssumption(); + return transitionMap = new ConcurrentHashMap<>(); + } } } @@ -311,7 +318,7 @@ return propertyMap; } - private ShapeImpl queryTransition(Transition transition) { + protected final ShapeImpl queryTransition(Transition transition) { ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition); if (cachedShape != null) { // Shape already exists? shapeCacheHitCount.inc(); @@ -332,9 +339,14 @@ @Override public ShapeImpl addProperty(Property property) { assert isValid(); - ShapeImpl nextShape = addPropertyInternal(property); - objectType.onPropertyAdded(property, this, nextShape); - return nextShape; + onPropertyTransition(property); + return addPropertyInternal(property); + } + + protected final void onPropertyTransition(Property property) { + if (sharedData instanceof ShapeListener) { + ((ShapeListener) sharedData).onPropertyTransition(property.getKey()); + } } /** @@ -627,6 +639,8 @@ @TruffleBoundary @Override public final ShapeImpl removeProperty(Property prop) { + onPropertyTransition(prop); + RemovePropertyTransition transition = new RemovePropertyTransition(prop); ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { @@ -667,6 +681,8 @@ return changeType(((ObjectTypeTransition) transition).getObjectType()); } else if (transition instanceof ReservePrimitiveArrayTransition) { return reservePrimitiveExtensionArray(); + } else if (transition instanceof DirectReplacePropertyTransition) { + return replaceProperty(((DirectReplacePropertyTransition) transition).getPropertyBefore(), ((DirectReplacePropertyTransition) transition).getPropertyAfter()); } else { throw new UnsupportedOperationException(); } @@ -681,8 +697,10 @@ * Duplicate shape exchanging existing property with new property. */ @Override - public final ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { - Transition replacePropertyTransition = new Transition.ReplacePropertyTransition(oldProperty, newProperty); + public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { + assert oldProperty.getKey().equals(newProperty.getKey()); + + Transition replacePropertyTransition = new Transition.IndirectReplacePropertyTransition(oldProperty, newProperty); ShapeImpl cachedShape = queryTransition(replacePropertyTransition); if (cachedShape != null) { return cachedShape; diff -r 0df6a0cb4b5f -r 0ab08be12bbb graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java Thu Jun 11 11:35:27 2015 +0200 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java Thu Jun 11 11:35:55 2015 +0200 @@ -133,10 +133,10 @@ } } - public static final class ReplacePropertyTransition extends PropertyTransition { + public abstract static class AbstractReplacePropertyTransition extends PropertyTransition { private final Property after; - public ReplacePropertyTransition(Property before, Property after) { + public AbstractReplacePropertyTransition(Property before, Property after) { super(before); this.after = after; } @@ -150,11 +150,41 @@ } @Override + public boolean equals(Object obj) { + return super.equals(obj) && this.after.equals(((AbstractReplacePropertyTransition) obj).after); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + after.hashCode(); + return result; + } + } + + public static final class IndirectReplacePropertyTransition extends AbstractReplacePropertyTransition { + public IndirectReplacePropertyTransition(Property before, Property after) { + super(before, after); + } + + @Override public boolean isDirect() { return false; } } + public static final class DirectReplacePropertyTransition extends AbstractReplacePropertyTransition { + public DirectReplacePropertyTransition(Property before, Property after) { + super(before, after); + } + + @Override + public boolean isDirect() { + return true; + } + } + public static final class ReservePrimitiveArrayTransition extends Transition { public ReservePrimitiveArrayTransition() { }