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}