blob: 2e2cacb78c0248cc186b4747497d2729a657ff27 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexander Astapchuk
*/
#if !defined(__JFRAME_H_INCLUDED__)
#define __JFRAME_H_INCLUDED__
/**
* @file
* @brief JFrame class declaration.
*/
#include "jdefs.h"
#include <vector>
#include <assert.h>
#include "val.h"
namespace Jitrino {
namespace Jet {
/**
* @brief Emulates Java method's frame (operand stack and local variables)
* and its operations.
*
* @todo Seems not much reasons to have it as separate class. Move all the
* data into BBState and drop off the JFrame?
*/
class JFrame {
public:
/**
* @brief No op.
*/
JFrame()
{
m_stack = m_vars = NULL;
max_stack = num_locals = 0;
m_top = -1;
};
~JFrame()
{
if (m_stack) {
delete[] m_stack;
}
if (m_vars) {
delete[] m_vars;
}
}
JFrame(const JFrame& that)
{
m_stack = m_vars = NULL;
max_stack = num_locals = 0;
m_top = -1;
*this = that;
}
public:
JFrame& operator=(const JFrame& that)
{
assert(that.m_stack != NULL);
assert(that.m_vars != NULL);
if (m_stack == NULL) {
max_stack = that.max_stack;
num_locals = that.num_locals;
m_stack = new Val[max_stack+1];
m_vars = new Val[num_locals];
}
else {
assert(max_stack == that.max_stack);
assert(num_locals== that.num_locals);
}
memcpy(m_stack, that.m_stack, sizeof(Val)*(max_stack+1));
memcpy(m_vars, that.m_vars, sizeof(Val)*(num_locals));
m_top = that.m_top;
return *this;
}
/**
* @brief Initializes empty JFrame with the given max stack depth,
* slots allocated for local variables and registers allocated
* for all this.
*/
void init(unsigned stack_max, unsigned var_slots)
{
assert(m_stack == NULL && m_vars == NULL);
max_stack = stack_max;
num_locals = var_slots;
m_stack = new Val[max_stack+1];
m_vars = new Val[num_locals];
m_top = -1;
}
/**
* @brief Converts slot index into depth.
*/
unsigned slot2depth(unsigned slot) const
{
assert(slot<size());
return size()-slot-1;
}
/**
* @brief Converts depth into slot index.
*/
unsigned depth2slot(unsigned depth) const
{
assert(depth<size());
return size()-depth-1;
}
/**
* @brief Returns current stack depth.
* @return current stack depth
*/
unsigned size(void) const
{
return m_top+1;
}
/**
* @brief Returns max stack size.
*/
unsigned max_size(void) const
{
return max_stack;
}
/**
* @brief Returns number of local variables.
*/
unsigned num_vars(void) const
{
return num_locals; //m_vars.size();
}
/**
* @brief Returns type of a slot at the given depth.
*/
jtype top(unsigned depth = 0) const
{
assert(depth<size());
return m_stack[size()-depth-1].type();
}
/**
* @brief Returns slot at the given depth.
*/
Val& dip(unsigned depth)
{
assert(depth<size());
return m_stack[size()-depth-1];
}
/**
* @brief Pushes the given jtype into the stack.
*/
void push(jtype jt);
/**
* @brief Pops out an item from the stack.
*
* The given \c jt must be same as the item on top of the stack.
*/
void pop(jtype jt);
/**
* @brief Pops 2 slots out of the stack - either a single wide item
* (#dbl64, #i64) or 2 one-slot items (#i32, #jobj, etc).
*/
void pop2(void);
/**
* @brief Pops out items specified by the array.
*
* Item of args[args.size()-1] is taken away from the top, and so on.
*/
void pop_n(const ::std::vector<jtype>& args);
/**
* @brief Returns stack slot at the given \b position (not depth).
*/
Val& at(unsigned slot)
{
assert(slot<size());
return m_stack[slot];
}
/**
* @brief Returns local variable at the given position.
*/
Val& var(unsigned slot)
{
assert(slot<num_vars()); //m_vars.size());
return m_vars[slot];
}
private:
/**
* @brief Current stack pointer. -1 if stack is empty.
*/
int m_top;
/**
* @brief Operand stack data.
*/
Val* m_stack;
/**
* @brief Local variables data.
*/
Val* m_vars;
unsigned max_stack;
unsigned num_locals;
};
}}; // ~namespace Jitrino::Jet
#endif // ~__JFRAME_H_INCLUDED__