/*
* 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 org.graalvm.compiler.truffle;
import java.lang.reflect.Method;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.truffle.OptimizedOSRLoopNode.OSRRootNode;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import jdk.vm.ci.code.stack.InspectedFrame;
public final class GraalFrameInstance implements FrameInstance {
private static final int CALL_TARGET_INDEX = 0;
private static final int CALL_TARGET_FRAME_INDEX = 1;
private static final int CALL_NODE_NOTIFY_INDEX = 0;
public static final Method CALL_TARGET_METHOD;
public static final Method CALL_NODE_METHOD;
public static final Method CALL_OSR_METHOD;
static {
try {
CALL_NODE_METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", Node.class, CallTarget.class, Object[].class, boolean.class);
CALL_TARGET_METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class);
CALL_OSR_METHOD = OptimizedOSRLoopNode.OSRRootNode.class.getDeclaredMethod("callProxy", OSRRootNode.class, VirtualFrame.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new GraalError(e);
}
}
private final InspectedFrame callTargetFrame;
private final InspectedFrame callNodeFrame;
public GraalFrameInstance(InspectedFrame callTargetFrame, InspectedFrame callNodeFrame) {
this.callTargetFrame = callTargetFrame;
this.callNodeFrame = callNodeFrame;
}
@SuppressWarnings("deprecation")
@Override
@TruffleBoundary
public Frame getFrame(FrameAccess access) {
if (access == FrameAccess.NONE) {
return null;
}
switch (access) {
case READ_ONLY: {
Frame frame = (Frame) callTargetFrame.getLocal(CALL_TARGET_FRAME_INDEX);
// assert that it is really used read only
assert (frame = new ReadOnlyFrame(frame)) != null;
return frame;
}
case READ_WRITE:
case MATERIALIZE:
if (callTargetFrame.isVirtual(CALL_TARGET_FRAME_INDEX)) {
callTargetFrame.materializeVirtualObjects(false);
}
Frame frame = (Frame) callTargetFrame.getLocal(CALL_TARGET_FRAME_INDEX);
if (access == FrameAccess.MATERIALIZE) {
frame = frame.materialize();
}
return frame;
default:
throw GraalError.unimplemented();
}
}
@Override
public boolean isVirtualFrame() {
return callTargetFrame.isVirtual(CALL_TARGET_FRAME_INDEX);
}
@Override
public CallTarget getCallTarget() {
return (CallTarget) callTargetFrame.getLocal(CALL_TARGET_INDEX);
}
@Override
public Node getCallNode() {
if (callNodeFrame != null) {
Object receiver = callNodeFrame.getLocal(CALL_NODE_NOTIFY_INDEX);
if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) {
return (Node) receiver;
}
}
return null;
}
}