001/* 002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.truffle; 024 025import java.lang.reflect.*; 026 027import jdk.internal.jvmci.code.stack.*; 028import jdk.internal.jvmci.common.*; 029 030import com.oracle.truffle.api.*; 031import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 032import com.oracle.truffle.api.frame.*; 033import com.oracle.truffle.api.nodes.*; 034 035public abstract class GraalFrameInstance implements FrameInstance { 036 037 protected final InspectedFrame stackFrame; 038 039 public GraalFrameInstance(InspectedFrame stackFrame) { 040 this.stackFrame = stackFrame; 041 } 042 043 protected abstract int getNotifyIndex(); 044 045 protected abstract int getFrameIndex(); 046 047 @TruffleBoundary 048 public Frame getFrame(FrameAccess access, boolean slowPath) { 049 if (access == FrameAccess.NONE) { 050 return null; 051 } 052 if (!slowPath && getNotifyIndex() != -1) { 053 MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex()); 054 if (notify != null) { 055 if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) { 056 notify.setOutsideFrameAccess(access); 057 } 058 if (stackFrame.isVirtual(getFrameIndex())) { 059 stackFrame.materializeVirtualObjects(true); 060 } 061 } 062 } 063 switch (access) { 064 case READ_ONLY: { 065 Frame frame = (Frame) stackFrame.getLocal(getFrameIndex()); 066 // assert that it is really used read only 067 assert (frame = new ReadOnlyFrame(frame)) != null; 068 return frame; 069 } 070 case READ_WRITE: 071 case MATERIALIZE: 072 if (stackFrame.isVirtual(getFrameIndex())) { 073 stackFrame.materializeVirtualObjects(false); 074 } 075 return (Frame) stackFrame.getLocal(getFrameIndex()); 076 default: 077 throw JVMCIError.unimplemented(); 078 } 079 } 080 081 public boolean isVirtualFrame() { 082 return stackFrame.isVirtual(getFrameIndex()); 083 } 084 085 public abstract CallTarget getCallTarget(); 086 087 public abstract Node getCallNode(); 088 089 /** 090 * This class represents a frame that is taken from the 091 * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean)} 092 * method. 093 */ 094 public static final class CallNodeFrame extends GraalFrameInstance { 095 public static final Method METHOD; 096 static { 097 try { 098 METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class); 099 } catch (NoSuchMethodException | SecurityException e) { 100 throw new JVMCIError(e); 101 } 102 } 103 private static final int NOTIFY_INDEX = 0; 104 private static final int FRAME_INDEX = 2; 105 106 public CallNodeFrame(InspectedFrame stackFrame) { 107 super(stackFrame); 108 } 109 110 @Override 111 protected int getNotifyIndex() { 112 return NOTIFY_INDEX; 113 } 114 115 @Override 116 protected int getFrameIndex() { 117 return FRAME_INDEX; 118 } 119 120 @Override 121 public CallTarget getCallTarget() { 122 return getCallNode().getRootNode().getCallTarget(); 123 } 124 125 @Override 126 public Node getCallNode() { 127 Object receiver = stackFrame.getLocal(getNotifyIndex()); 128 if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) { 129 return (Node) receiver; 130 } 131 return null; 132 } 133 } 134 135 /** 136 * This class represents a frame that is taken from the {@link OptimizedCallTarget#callProxy} 137 * method. 138 */ 139 public static final class CallTargetFrame extends GraalFrameInstance { 140 public static final Method METHOD; 141 static { 142 try { 143 METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class); 144 } catch (NoSuchMethodException | SecurityException e) { 145 throw new JVMCIError(e); 146 } 147 } 148 private static final int NOTIFY_INDEX = -1; 149 private static final int CALL_TARGET_INDEX = 0; 150 private static final int FRAME_INDEX = 1; 151 private final boolean currentFrame; 152 153 public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) { 154 super(stackFrame); 155 this.currentFrame = currentFrame; 156 } 157 158 @Override 159 public Frame getFrame(FrameAccess access, boolean slowPath) { 160 if (!slowPath && currentFrame) { 161 throw new UnsupportedOperationException("cannot access current frame as fast path"); 162 } 163 return super.getFrame(access, slowPath); 164 } 165 166 @Override 167 protected int getNotifyIndex() { 168 return NOTIFY_INDEX; 169 } 170 171 @Override 172 protected int getFrameIndex() { 173 return FRAME_INDEX; 174 } 175 176 @Override 177 public CallTarget getCallTarget() { 178 return (CallTarget) stackFrame.getLocal(CALL_TARGET_INDEX); 179 } 180 181 @Override 182 public Node getCallNode() { 183 return null; 184 } 185 } 186}