001/* 002 * Copyright (c) 2013, 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.util.*; 026 027import com.oracle.truffle.api.*; 028import com.oracle.truffle.api.frame.*; 029 030/** 031 * More efficient implementation of the Truffle frame that has no safety checks for frame accesses 032 * and therefore is much faster. Should not be used during debugging as potential misuses of the 033 * frame object would show up very late and would be hard to identify. 034 */ 035public final class FrameWithBoxing implements VirtualFrame, MaterializedFrame { 036 private final FrameDescriptor descriptor; 037 private final Object[] arguments; 038 private Object[] locals; 039 040 public FrameWithBoxing(FrameDescriptor descriptor, Object[] arguments) { 041 this.descriptor = descriptor; 042 this.arguments = arguments; 043 int size = descriptor.getSize(); 044 this.locals = new Object[size]; 045 Object defaultValue = descriptor.getDefaultValue(); 046 if (defaultValue != null) { 047 Arrays.fill(locals, defaultValue); 048 } 049 } 050 051 @Override 052 public Object[] getArguments() { 053 return unsafeCast(arguments, Object[].class, true, true); 054 } 055 056 @Override 057 public MaterializedFrame materialize() { 058 return this; 059 } 060 061 @Override 062 public Object getObject(FrameSlot slot) { 063 int index = slot.getIndex(); 064 Object[] curLocals = this.getLocals(); 065 if (CompilerDirectives.inInterpreter() && index >= curLocals.length) { 066 curLocals = resizeAndCheck(slot); 067 } 068 return curLocals[index]; 069 } 070 071 private Object[] getLocals() { 072 return unsafeCast(locals, Object[].class, true, true); 073 } 074 075 @Override 076 public void setObject(FrameSlot slot, Object value) { 077 int index = slot.getIndex(); 078 Object[] curLocals = this.getLocals(); 079 if (CompilerDirectives.inInterpreter() && index >= curLocals.length) { 080 curLocals = resizeAndCheck(slot); 081 } 082 curLocals[index] = value; 083 } 084 085 @Override 086 public byte getByte(FrameSlot slot) throws FrameSlotTypeException { 087 Object result = getObject(slot); 088 if (CompilerDirectives.inInterpreter() && !(result instanceof Byte)) { 089 throw new FrameSlotTypeException(); 090 } 091 return (Byte) result; 092 } 093 094 @Override 095 public void setByte(FrameSlot slot, byte value) { 096 setObject(slot, value); 097 } 098 099 @Override 100 public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { 101 Object result = getObject(slot); 102 if (CompilerDirectives.inInterpreter() && !(result instanceof Boolean)) { 103 throw new FrameSlotTypeException(); 104 } 105 return (Boolean) result; 106 } 107 108 @Override 109 public void setBoolean(FrameSlot slot, boolean value) { 110 setObject(slot, value); 111 } 112 113 @Override 114 public float getFloat(FrameSlot slot) throws FrameSlotTypeException { 115 Object result = getObject(slot); 116 if (CompilerDirectives.inInterpreter() && !(result instanceof Float)) { 117 throw new FrameSlotTypeException(); 118 } 119 return (Float) result; 120 } 121 122 @Override 123 public void setFloat(FrameSlot slot, float value) { 124 setObject(slot, value); 125 } 126 127 @Override 128 public long getLong(FrameSlot slot) throws FrameSlotTypeException { 129 Object result = getObject(slot); 130 if (CompilerDirectives.inInterpreter() && !(result instanceof Long)) { 131 throw new FrameSlotTypeException(); 132 } 133 return (Long) result; 134 } 135 136 @Override 137 public void setLong(FrameSlot slot, long value) { 138 setObject(slot, value); 139 } 140 141 @Override 142 public int getInt(FrameSlot slot) throws FrameSlotTypeException { 143 Object result = getObject(slot); 144 if (CompilerDirectives.inInterpreter() && !(result instanceof Integer)) { 145 throw new FrameSlotTypeException(); 146 } 147 return (Integer) result; 148 } 149 150 @Override 151 public void setInt(FrameSlot slot, int value) { 152 setObject(slot, value); 153 } 154 155 @Override 156 public double getDouble(FrameSlot slot) throws FrameSlotTypeException { 157 Object result = getObject(slot); 158 if (CompilerDirectives.inInterpreter() && !(result instanceof Double)) { 159 throw new FrameSlotTypeException(); 160 } 161 return (Double) result; 162 } 163 164 @Override 165 public void setDouble(FrameSlot slot, double value) { 166 setObject(slot, value); 167 } 168 169 @Override 170 public FrameDescriptor getFrameDescriptor() { 171 return this.descriptor; 172 } 173 174 private Object[] resizeAndCheck(FrameSlot slot) { 175 if (!resize()) { 176 throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); 177 } 178 return locals; 179 } 180 181 @Override 182 public Object getValue(FrameSlot slot) { 183 return getObject(slot); 184 } 185 186 private boolean resize() { 187 int oldSize = locals.length; 188 int newSize = descriptor.getSize(); 189 if (newSize > oldSize) { 190 locals = Arrays.copyOf(locals, newSize); 191 Arrays.fill(locals, oldSize, newSize, descriptor.getDefaultValue()); 192 return true; 193 } 194 return false; 195 } 196 197 @Override 198 public boolean isObject(FrameSlot slot) { 199 return getObject(slot) != null; 200 } 201 202 @Override 203 public boolean isByte(FrameSlot slot) { 204 return getObject(slot) instanceof Byte; 205 } 206 207 @Override 208 public boolean isBoolean(FrameSlot slot) { 209 return getObject(slot) instanceof Boolean; 210 } 211 212 @Override 213 public boolean isInt(FrameSlot slot) { 214 return getObject(slot) instanceof Integer; 215 } 216 217 @Override 218 public boolean isLong(FrameSlot slot) { 219 return getObject(slot) instanceof Long; 220 } 221 222 @Override 223 public boolean isFloat(FrameSlot slot) { 224 return getObject(slot) instanceof Float; 225 } 226 227 @Override 228 public boolean isDouble(FrameSlot slot) { 229 return getObject(slot) instanceof Double; 230 } 231 232 @SuppressWarnings({"unchecked", "unused"}) 233 static <T> T unsafeCast(Object value, Class<T> type, boolean condition, boolean nonNull) { 234 return (T) value; 235 } 236}