# HG changeset patch # User Christian Wimmer # Date 1411525426 25200 # Node ID d0d76deeacb94b0036f509406af85d1534db135a # Parent be733832464dad304aa6dfecfffd755e7a72c920 Make more Truffle code HotSpot independent, and allow more customization by subclasses diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java Tue Sep 23 19:22:45 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2014, 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.truffle.hotspot; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.stack.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.truffle.*; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.SlowPath; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -public abstract class HotSpotFrameInstance implements FrameInstance { - - protected final InspectedFrame stackFrame; - - public HotSpotFrameInstance(InspectedFrame stackFrame) { - this.stackFrame = stackFrame; - } - - protected abstract int getNotifyIndex(); - - protected abstract int getFrameIndex(); - - @SlowPath - public Frame getFrame(FrameAccess access, boolean slowPath) { - if (access == FrameAccess.NONE) { - return null; - } - if (!slowPath && getNotifyIndex() != -1) { - MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex()); - if (notify != null) { - if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) { - notify.setOutsideFrameAccess(access); - } - if (stackFrame.isVirtual(getFrameIndex())) { - stackFrame.materializeVirtualObjects(true); - } - } - } - switch (access) { - case READ_ONLY: { - Frame frame = (Frame) stackFrame.getLocal(getFrameIndex()); - // assert that it is really used read only - assert (frame = new ReadOnlyFrame(frame)) != null; - return frame; - } - case READ_WRITE: - case MATERIALIZE: - if (stackFrame.isVirtual(getFrameIndex())) { - stackFrame.materializeVirtualObjects(false); - } - return (Frame) stackFrame.getLocal(getFrameIndex()); - default: - throw GraalInternalError.unimplemented(); - } - } - - public boolean isVirtualFrame() { - return stackFrame.isVirtual(getFrameIndex()); - } - - public abstract CallTarget getCallTarget(); - - public abstract Node getCallNode(); - - /** - * This class represents a frame that is taken from the - * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)} - * method. - */ - public static final class CallNodeFrame extends HotSpotFrameInstance { - public static final Method METHOD; - static { - try { - METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class, boolean.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(e); - } - } - private static final int NOTIFY_INDEX = 0; - private static final int FRAME_INDEX = 2; - - public CallNodeFrame(InspectedFrame stackFrame) { - super(stackFrame); - } - - @Override - protected int getNotifyIndex() { - return NOTIFY_INDEX; - } - - @Override - protected int getFrameIndex() { - return FRAME_INDEX; - } - - @Override - public CallTarget getCallTarget() { - return getCallNode().getRootNode().getCallTarget(); - } - - @Override - public Node getCallNode() { - Object receiver = stackFrame.getLocal(getNotifyIndex()); - if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) { - return (Node) receiver; - } - return null; - } - } - - /** - * This class represents a frame that is taken from the {@link OptimizedCallTarget#callProxy} - * method. - */ - public static final class CallTargetFrame extends HotSpotFrameInstance { - public static final Method METHOD; - static { - try { - METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(e); - } - } - private static final int NOTIFY_INDEX = -1; - private static final int CALL_TARGET_INDEX = 0; - private static final int FRAME_INDEX = 1; - private final boolean currentFrame; - - public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) { - super(stackFrame); - this.currentFrame = currentFrame; - } - - @Override - public Frame getFrame(FrameAccess access, boolean slowPath) { - if (!slowPath && currentFrame) { - throw new UnsupportedOperationException("cannot access current frame as fast path"); - } - return super.getFrame(access, slowPath); - } - - @Override - protected int getNotifyIndex() { - return NOTIFY_INDEX; - } - - @Override - protected int getFrameIndex() { - return FRAME_INDEX; - } - - @Override - public CallTarget getCallTarget() { - return (CallTarget) stackFrame.getLocal(CALL_TARGET_INDEX); - } - - @Override - public Node getCallNode() { - return null; - } - } -} diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Sep 23 19:22:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Sep 23 19:23:46 2014 -0700 @@ -34,7 +34,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; -import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.*; @@ -57,15 +56,12 @@ import com.oracle.graal.truffle.*; import com.oracle.graal.word.*; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.SlowPath; -import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.Node; /** * Implementation of the Truffle runtime when running on top of Graal. */ -public final class HotSpotTruffleRuntime implements GraalTruffleRuntime { +public final class HotSpotTruffleRuntime extends GraalTruffleRuntime { public static HotSpotTruffleRuntime makeInstance() { return new HotSpotTruffleRuntime(); @@ -73,23 +69,14 @@ private TruffleCompilerImpl truffleCompiler; private Replacements truffleReplacements; - private StackIntrospection stackIntrospection; - private ArrayList includes; - private ArrayList excludes; private Map> compilations = newIdentityMap(); private final ThreadPoolExecutor compileQueue; - private final ResolvedJavaMethod[] callNodeMethod; - private final ResolvedJavaMethod[] callTargetMethod; - private final ResolvedJavaMethod[] anyFrameMethod; private final Map callTargets = Collections.synchronizedMap(new WeakHashMap()); private HotSpotTruffleRuntime() { installOptimizedCallTargetCallMethod(); - - callNodeMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallNodeFrame.METHOD)}; - callTargetMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallTargetFrame.METHOD)}; - anyFrameMethod = new ResolvedJavaMethod[]{callNodeMethod[0], callTargetMethod[0]}; + lookupCallMethods(getGraalProviders().getMetaAccess()); // Create compilation queue. CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new CompilerThreadFactory.DebugConfigAccess() { @@ -106,10 +93,12 @@ compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); } + @Override public String getName() { return "Graal Truffle Runtime"; } + @Override public RootCallTarget createCallTarget(RootNode rootNode) { CompilationPolicy compilationPolicy; if (acceptForCompilation(rootNode)) { @@ -123,50 +112,7 @@ return target; } - public LoopNode createLoopNode(RepeatingNode repeating) { - if (!(repeating instanceof Node)) { - throw new IllegalArgumentException("Repeating node must be of type Node."); - } - return new OptimizedLoopNode(repeating); - } - - public DirectCallNode createDirectCallNode(CallTarget target) { - if (target instanceof OptimizedCallTarget) { - return new OptimizedDirectCallNode((OptimizedCallTarget) target); - } else { - throw new IllegalStateException(String.format("Unexpected call target class %s!", target.getClass())); - } - } - - public IndirectCallNode createIndirectCallNode() { - return new OptimizedIndirectCallNode(); - } - @Override - public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) { - return OptimizedCallTarget.createFrame(frameDescriptor, arguments); - } - - @Override - public MaterializedFrame createMaterializedFrame(Object[] arguments) { - return createMaterializedFrame(arguments, new FrameDescriptor()); - } - - @Override - public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) { - return new FrameWithoutBoxing(frameDescriptor, arguments); - } - - @Override - public Assumption createAssumption() { - return createAssumption(null); - } - - @Override - public Assumption createAssumption(String name) { - return new OptimizedAssumption(name); - } - public Replacements getReplacements() { if (truffleReplacements == null) { truffleReplacements = HotSpotTruffleReplacements.makeInstance(); @@ -174,45 +120,6 @@ return truffleReplacements; } - private boolean acceptForCompilation(RootNode rootNode) { - if (TruffleCompileOnly.getValue() != null) { - if (includes == null) { - parseCompileOnly(); - } - - String name = rootNode.toString(); - boolean included = includes.isEmpty(); - for (int i = 0; !included && i < includes.size(); i++) { - if (name.contains(includes.get(i))) { - included = true; - } - } - if (!included) { - return false; - } - for (String exclude : excludes) { - if (name.contains(exclude)) { - return false; - } - } - } - return true; - } - - private void parseCompileOnly() { - includes = new ArrayList<>(); - excludes = new ArrayList<>(); - - String[] items = TruffleCompileOnly.getValue().split(","); - for (String item : items) { - if (item.startsWith("~")) { - excludes.add(item.substring(1)); - } else { - includes.add(item); - } - } - } - public static void installOptimizedCallTargetCallMethod() { Providers providers = getGraalProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); @@ -272,53 +179,7 @@ } } - @SlowPath @Override - public T iterateFrames(FrameInstanceVisitor visitor) { - initStackIntrospection(); - - InspectedFrameVisitor inspectedFrameVisitor = new InspectedFrameVisitor() { - private boolean skipNext = false; - - public T visitFrame(InspectedFrame frame) { - if (skipNext) { - assert frame.isMethod(callTargetMethod[0]); - skipNext = false; - return null; - } - - if (frame.isMethod(callNodeMethod[0])) { - skipNext = true; - return visitor.visitFrame(new HotSpotFrameInstance.CallNodeFrame(frame)); - } else { - assert frame.isMethod(callTargetMethod[0]); - return visitor.visitFrame(new HotSpotFrameInstance.CallTargetFrame(frame, false)); - } - - } - }; - return stackIntrospection.iterateFrames(anyFrameMethod, anyFrameMethod, 1, inspectedFrameVisitor); - } - - private void initStackIntrospection() { - if (stackIntrospection == null) { - stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); - } - } - - @Override - public FrameInstance getCallerFrame() { - return iterateFrames(frame -> frame); - } - - @SlowPath - @Override - public FrameInstance getCurrentFrame() { - initStackIntrospection(); - - return stackIntrospection.iterateFrames(callTargetMethod, callTargetMethod, 0, frame -> new HotSpotFrameInstance.CallTargetFrame(frame, true)); - } - public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) { if (truffleCompiler == null) { truffleCompiler = new TruffleCompilerImpl(); @@ -346,6 +207,7 @@ } } + @Override public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget) { Future codeTask = this.compilations.get(optimizedCallTarget); if (codeTask != null && isCompiling(optimizedCallTarget)) { @@ -355,6 +217,7 @@ return false; } + @Override public void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException { Future codeTask = this.compilations.get(optimizedCallTarget); if (codeTask != null && isCompiling(optimizedCallTarget)) { @@ -366,6 +229,7 @@ } } + @Override public boolean isCompiling(OptimizedCallTarget optimizedCallTarget) { Future codeTask = this.compilations.get(optimizedCallTarget); if (codeTask != null) { @@ -378,10 +242,12 @@ return false; } + @Override public void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget) { HotSpotGraalRuntime.runtime().getCompilerToVM().invalidateInstalledCode(optimizedCallTarget); } + @Override public void reinstallStubs() { installOptimizedCallTargetCallMethod(); } @@ -391,6 +257,7 @@ return Collections.unmodifiableSet(callTargets.keySet()); } + @Override public void notifyTransferToInterpreter() { CompilerAsserts.neverPartOfCompilation(); if (TraceTruffleTransferToInterpreter.getValue()) { diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java Tue Sep 23 19:22:45 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2014, 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.truffle.hotspot; - -import com.oracle.graal.compiler.common.*; -import com.oracle.truffle.api.frame.*; - -class ReadOnlyFrame implements Frame { - private final Frame delegate; - - public ReadOnlyFrame(Frame delegate) { - this.delegate = delegate; - } - - public FrameDescriptor getFrameDescriptor() { - return delegate.getFrameDescriptor(); - } - - public Object[] getArguments() { - return delegate.getArguments().clone(); - } - - public Object getObject(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getObject(slot); - } - - public void setObject(FrameSlot slot, Object value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public byte getByte(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getByte(slot); - } - - public void setByte(FrameSlot slot, byte value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getBoolean(slot); - } - - public void setBoolean(FrameSlot slot, boolean value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public int getInt(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getInt(slot); - } - - public void setInt(FrameSlot slot, int value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public long getLong(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getLong(slot); - } - - public void setLong(FrameSlot slot, long value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public float getFloat(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getFloat(slot); - } - - public void setFloat(FrameSlot slot, float value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public double getDouble(FrameSlot slot) throws FrameSlotTypeException { - return delegate.getDouble(slot); - } - - public void setDouble(FrameSlot slot, double value) { - throw GraalInternalError.shouldNotReachHere(); - } - - public Object getValue(FrameSlot slot) { - return delegate.getValue(slot); - } - - public MaterializedFrame materialize() { - throw GraalInternalError.shouldNotReachHere(); - } - - public boolean isObject(FrameSlot slot) { - return delegate.isObject(slot); - } - - public boolean isByte(FrameSlot slot) { - return delegate.isByte(slot); - } - - public boolean isBoolean(FrameSlot slot) { - return delegate.isBoolean(slot); - } - - public boolean isInt(FrameSlot slot) { - return delegate.isInt(slot); - } - - public boolean isLong(FrameSlot slot) { - return delegate.isLong(slot); - } - - public boolean isFloat(FrameSlot slot) { - return delegate.isFloat(slot); - } - - public boolean isDouble(FrameSlot slot) { - return delegate.isDouble(slot); - } -} \ No newline at end of file diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalFrameInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalFrameInstance.java Tue Sep 23 19:23:46 2014 -0700 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2014, 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.truffle; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.stack.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public abstract class GraalFrameInstance implements FrameInstance { + + protected final InspectedFrame stackFrame; + + public GraalFrameInstance(InspectedFrame stackFrame) { + this.stackFrame = stackFrame; + } + + protected abstract int getNotifyIndex(); + + protected abstract int getFrameIndex(); + + @SlowPath + public Frame getFrame(FrameAccess access, boolean slowPath) { + if (access == FrameAccess.NONE) { + return null; + } + if (!slowPath && getNotifyIndex() != -1) { + MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex()); + if (notify != null) { + if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) { + notify.setOutsideFrameAccess(access); + } + if (stackFrame.isVirtual(getFrameIndex())) { + stackFrame.materializeVirtualObjects(true); + } + } + } + switch (access) { + case READ_ONLY: { + Frame frame = (Frame) stackFrame.getLocal(getFrameIndex()); + // assert that it is really used read only + assert (frame = new ReadOnlyFrame(frame)) != null; + return frame; + } + case READ_WRITE: + case MATERIALIZE: + if (stackFrame.isVirtual(getFrameIndex())) { + stackFrame.materializeVirtualObjects(false); + } + return (Frame) stackFrame.getLocal(getFrameIndex()); + default: + throw GraalInternalError.unimplemented(); + } + } + + public boolean isVirtualFrame() { + return stackFrame.isVirtual(getFrameIndex()); + } + + public abstract CallTarget getCallTarget(); + + public abstract Node getCallNode(); + + /** + * This class represents a frame that is taken from the + * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)} + * method. + */ + public static final class CallNodeFrame extends GraalFrameInstance { + public static final Method METHOD; + static { + try { + METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class, boolean.class); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } + private static final int NOTIFY_INDEX = 0; + private static final int FRAME_INDEX = 2; + + public CallNodeFrame(InspectedFrame stackFrame) { + super(stackFrame); + } + + @Override + protected int getNotifyIndex() { + return NOTIFY_INDEX; + } + + @Override + protected int getFrameIndex() { + return FRAME_INDEX; + } + + @Override + public CallTarget getCallTarget() { + return getCallNode().getRootNode().getCallTarget(); + } + + @Override + public Node getCallNode() { + Object receiver = stackFrame.getLocal(getNotifyIndex()); + if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) { + return (Node) receiver; + } + return null; + } + } + + /** + * This class represents a frame that is taken from the {@link OptimizedCallTarget#callProxy} + * method. + */ + public static final class CallTargetFrame extends GraalFrameInstance { + public static final Method METHOD; + static { + try { + METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } + private static final int NOTIFY_INDEX = -1; + private static final int CALL_TARGET_INDEX = 0; + private static final int FRAME_INDEX = 1; + private final boolean currentFrame; + + public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) { + super(stackFrame); + this.currentFrame = currentFrame; + } + + @Override + public Frame getFrame(FrameAccess access, boolean slowPath) { + if (!slowPath && currentFrame) { + throw new UnsupportedOperationException("cannot access current frame as fast path"); + } + return super.getFrame(access, slowPath); + } + + @Override + protected int getNotifyIndex() { + return NOTIFY_INDEX; + } + + @Override + protected int getFrameIndex() { + return FRAME_INDEX; + } + + @Override + public CallTarget getCallTarget() { + return (CallTarget) stackFrame.getLocal(CALL_TARGET_INDEX); + } + + @Override + public Node getCallNode() { + return null; + } + } +} diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Tue Sep 23 19:22:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Tue Sep 23 19:23:46 2014 -0700 @@ -22,24 +22,180 @@ */ package com.oracle.graal.truffle; +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; import java.util.concurrent.*; +import com.oracle.graal.api.code.stack.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; -public interface GraalTruffleRuntime extends TruffleRuntime { +public abstract class GraalTruffleRuntime implements TruffleRuntime { + + private ArrayList includes; + private ArrayList excludes; + + private StackIntrospection stackIntrospection; + protected ResolvedJavaMethod[] callNodeMethod; + protected ResolvedJavaMethod[] callTargetMethod; + protected ResolvedJavaMethod[] anyFrameMethod; + + protected void lookupCallMethods(MetaAccessProvider metaAccess) { + callNodeMethod = new ResolvedJavaMethod[]{metaAccess.lookupJavaMethod(GraalFrameInstance.CallNodeFrame.METHOD)}; + callTargetMethod = new ResolvedJavaMethod[]{metaAccess.lookupJavaMethod(GraalFrameInstance.CallTargetFrame.METHOD)}; + anyFrameMethod = new ResolvedJavaMethod[]{callNodeMethod[0], callTargetMethod[0]}; + } + + @Override + public LoopNode createLoopNode(RepeatingNode repeating) { + if (!(repeating instanceof Node)) { + throw new IllegalArgumentException("Repeating node must be of type Node."); + } + return new OptimizedLoopNode(repeating); + } + + @Override + public DirectCallNode createDirectCallNode(CallTarget target) { + if (target instanceof OptimizedCallTarget) { + return new OptimizedDirectCallNode((OptimizedCallTarget) target); + } else { + throw new IllegalStateException(String.format("Unexpected call target class %s!", target.getClass())); + } + } - Replacements getReplacements(); + @Override + public IndirectCallNode createIndirectCallNode() { + return new OptimizedIndirectCallNode(); + } + + @Override + public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) { + return OptimizedCallTarget.createFrame(frameDescriptor, arguments); + } + + @Override + public MaterializedFrame createMaterializedFrame(Object[] arguments) { + return createMaterializedFrame(arguments, new FrameDescriptor()); + } + + @Override + public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) { + return new FrameWithoutBoxing(frameDescriptor, arguments); + } - void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous); + @Override + public Assumption createAssumption() { + return createAssumption(null); + } + + @Override + public Assumption createAssumption(String name) { + return new OptimizedAssumption(name); + } - boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget); + @SlowPath + @Override + public T iterateFrames(FrameInstanceVisitor visitor) { + initStackIntrospection(); + + InspectedFrameVisitor inspectedFrameVisitor = new InspectedFrameVisitor() { + private boolean skipNext = false; + + public T visitFrame(InspectedFrame frame) { + if (skipNext) { + assert frame.isMethod(callTargetMethod[0]); + skipNext = false; + return null; + } - void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException; + if (frame.isMethod(callNodeMethod[0])) { + skipNext = true; + return visitor.visitFrame(new GraalFrameInstance.CallNodeFrame(frame)); + } else { + assert frame.isMethod(callTargetMethod[0]); + return visitor.visitFrame(new GraalFrameInstance.CallTargetFrame(frame, false)); + } + + } + }; + return stackIntrospection.iterateFrames(anyFrameMethod, anyFrameMethod, 1, inspectedFrameVisitor); + } + + private void initStackIntrospection() { + if (stackIntrospection == null) { + stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); + } + } - boolean isCompiling(OptimizedCallTarget optimizedCallTarget); + @Override + public FrameInstance getCallerFrame() { + return iterateFrames(frame -> frame); + } + + @SlowPath + @Override + public FrameInstance getCurrentFrame() { + initStackIntrospection(); + + return stackIntrospection.iterateFrames(callTargetMethod, callTargetMethod, 0, frame -> new GraalFrameInstance.CallTargetFrame(frame, true)); + } + + protected boolean acceptForCompilation(RootNode rootNode) { + if (TruffleCompileOnly.getValue() != null) { + if (includes == null) { + parseCompileOnly(); + } - void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget); + String name = rootNode.toString(); + boolean included = includes.isEmpty(); + for (int i = 0; !included && i < includes.size(); i++) { + if (name.contains(includes.get(i))) { + included = true; + } + } + if (!included) { + return false; + } + for (String exclude : excludes) { + if (name.contains(exclude)) { + return false; + } + } + } + return true; + } + + protected void parseCompileOnly() { + includes = new ArrayList<>(); + excludes = new ArrayList<>(); - void reinstallStubs(); + String[] items = TruffleCompileOnly.getValue().split(","); + for (String item : items) { + if (item.startsWith("~")) { + excludes.add(item.substring(1)); + } else { + includes.add(item); + } + } + } + + public abstract Replacements getReplacements(); + + public abstract void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous); + + public abstract boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget); + + public abstract void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException; + + public abstract boolean isCompiling(OptimizedCallTarget optimizedCallTarget); + + public abstract void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget); + + public abstract void reinstallStubs(); } diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Tue Sep 23 19:22:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Tue Sep 23 19:23:46 2014 -0700 @@ -182,7 +182,7 @@ log(0, "opt fail", callSite.toString(), properties); } - static void logOptimizingDone(OptimizedCallTarget target, Map properties) { + public static void logOptimizingDone(OptimizedCallTarget target, Map properties) { if (TraceTruffleCompilationDetails.getValue() || TraceTruffleCompilation.getValue()) { log(0, "opt done", target.toString(), properties); } @@ -223,7 +223,7 @@ } } - static void addASTSizeProperty(OptimizedCallTarget target, Map properties) { + public static void addASTSizeProperty(OptimizedCallTarget target, Map properties) { int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { public boolean isCounted(Node node) { return node.getCost() == NodeCost.POLYMORPHIC; diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Tue Sep 23 19:22:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Tue Sep 23 19:23:46 2014 -0700 @@ -29,7 +29,7 @@ import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; import com.oracle.truffle.api.nodes.NodeUtil.NodeField; -class OptimizedCallUtils { +public class OptimizedCallUtils { public static int countCalls(OptimizedCallTarget target) { return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/ReadOnlyFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/ReadOnlyFrame.java Tue Sep 23 19:23:46 2014 -0700 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014, 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.truffle; + +import com.oracle.graal.compiler.common.*; +import com.oracle.truffle.api.frame.*; + +class ReadOnlyFrame implements Frame { + private final Frame delegate; + + public ReadOnlyFrame(Frame delegate) { + this.delegate = delegate; + } + + public FrameDescriptor getFrameDescriptor() { + return delegate.getFrameDescriptor(); + } + + public Object[] getArguments() { + return delegate.getArguments().clone(); + } + + public Object getObject(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getObject(slot); + } + + public void setObject(FrameSlot slot, Object value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public byte getByte(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getByte(slot); + } + + public void setByte(FrameSlot slot, byte value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getBoolean(slot); + } + + public void setBoolean(FrameSlot slot, boolean value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public int getInt(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getInt(slot); + } + + public void setInt(FrameSlot slot, int value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public long getLong(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getLong(slot); + } + + public void setLong(FrameSlot slot, long value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public float getFloat(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getFloat(slot); + } + + public void setFloat(FrameSlot slot, float value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public double getDouble(FrameSlot slot) throws FrameSlotTypeException { + return delegate.getDouble(slot); + } + + public void setDouble(FrameSlot slot, double value) { + throw GraalInternalError.shouldNotReachHere(); + } + + public Object getValue(FrameSlot slot) { + return delegate.getValue(slot); + } + + public MaterializedFrame materialize() { + throw GraalInternalError.shouldNotReachHere(); + } + + public boolean isObject(FrameSlot slot) { + return delegate.isObject(slot); + } + + public boolean isByte(FrameSlot slot) { + return delegate.isByte(slot); + } + + public boolean isBoolean(FrameSlot slot) { + return delegate.isBoolean(slot); + } + + public boolean isInt(FrameSlot slot) { + return delegate.isInt(slot); + } + + public boolean isLong(FrameSlot slot) { + return delegate.isLong(slot); + } + + public boolean isFloat(FrameSlot slot) { + return delegate.isFloat(slot); + } + + public boolean isDouble(FrameSlot slot) { + return delegate.isDouble(slot); + } +} \ No newline at end of file diff -r be733832464d -r d0d76deeacb9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Tue Sep 23 19:22:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Tue Sep 23 19:23:46 2014 -0700 @@ -52,7 +52,7 @@ /** * Implementation of a cache for Truffle graphs for improving partial evaluation time. */ -public final class TruffleCacheImpl implements TruffleCache { +public class TruffleCacheImpl implements TruffleCache { private final Providers providers; private final GraphBuilderConfiguration config; @@ -123,14 +123,18 @@ lookupExceedsMaxSize(); } - lastUsed.put(key, counter++); - cache.put(key, markerGraph); try (Scope s = Debug.scope("TruffleCache", providers.getMetaAccess(), method)) { - final StructuredGraph graph = new StructuredGraph(method); final PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false)); - Mark mark = graph.getMark(); - new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph); + Mark mark = null; + + final StructuredGraph graph = parseGraph(method, phaseContext); + if (graph == null) { + return null; + } + + lastUsed.put(key, counter++); + cache.put(key, markerGraph); for (ParameterNode param : graph.getNodes(ParameterNode.class)) { if (param.getKind() == Kind.Object) { @@ -249,11 +253,20 @@ canonicalizer.applyIncremental(graph, phaseContext, canonicalizerUsages); } + protected StructuredGraph parseGraph(final ResolvedJavaMethod method, final PhaseContext phaseContext) { + final StructuredGraph graph = new StructuredGraph(method); + new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph); + return graph; + } + private void expandInvoke(MethodCallTargetNode methodCallTargetNode, CanonicalizerPhase canonicalizer) { StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod()); if (inlineGraph == null) { inlineGraph = TruffleCacheImpl.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, canonicalizer, false); } + if (inlineGraph == null) { + return; + } if (inlineGraph == this.markerGraph) { // Can happen for recursive calls. throw GraphUtil.approxSourceException(methodCallTargetNode, new IllegalStateException("Found illegal recursive call to " + methodCallTargetNode.targetMethod() + @@ -281,7 +294,7 @@ return false; } - private boolean shouldInline(MethodCallTargetNode methodCallTargetNode) { + protected boolean shouldInline(MethodCallTargetNode methodCallTargetNode) { boolean result = (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && methodCallTargetNode.targetMethod().canBeInlined() && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null &&