/*
* $Id: StackFrame.java,v 1.19 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script;
import anvil.Location;
import anvil.core.Any;
import anvil.core.AnyClass;
import anvil.core.Serializer;
import anvil.core.Unserializer;
import anvil.core.UnserializationException;
import anvil.server.Zone;
import java.util.Arrays;
import java.io.IOException;
/**
* class StackFrame
* @author Jani Lehtim�ki
*/
public class StackFrame
{
protected Any[] _locals;
protected int _maxlocals;
protected Module _module;
protected AnyClass _self;
protected Function _function;
protected int _line;
protected Any[] _stack = null;
protected int _stackptr = 0;
protected Zone _zone = null;
protected boolean _escaped = false;
protected StackFrame _escape = null;
private StackFrame()
{
}
public StackFrame(Module module, AnyClass self, Function function, int maxLocals, int line, boolean escaped)
{
init(module, self, function, maxLocals, line, escaped);
}
public void init(Module module, AnyClass self, Function function, int maxLocals, int line, boolean escaped)
{
_module = module;
_self = self;
_function = function;
_line = line;
if (maxLocals > 0) {
if (_locals == null) {
_locals = new Any[maxLocals];
} else if (_locals.length < maxLocals) {
_locals = new Any[maxLocals];
}
java.util.Arrays.fill(_locals, 0, maxLocals, Any.UNDEFINED);
_maxlocals = maxLocals;
}
_escaped = escaped;
}
public void clear()
{
if (_locals != null) {
Arrays.fill(_locals, null);
}
_module = null;
_self = null;
_function = null;
_zone = null;
_stackptr = 0;
if (_stack != null) {
Arrays.fill(_stack, null);
}
}
public void detach()
{
_module = null;
_self = null;
_function = null;
_zone = null;
if (_stack != null) {
Arrays.fill(_stack, null);
_stack = null;
}
}
public void destroy()
{
_locals = null;
_module = null;
_self = null;
_function = null;
_zone = null;
_stackptr = 0;
_stack = null;
}
public Function getFunction()
{
return _function;
}
public Any getLocal(int index)
{
return _locals[index];
}
public Any setLocal(int index, Any value)
{
return _locals[index] = value;
}
public Any getLocal(int depth, int index)
{
StackFrame frame = _escape;
while(--depth > 0) {
frame = frame.getEscape();
}
return frame.getLocal(index);
}
public Any setLocal(int depth, int index, Any value)
{
StackFrame frame = _escape;
while(--depth > 0) {
frame = frame.getEscape();
}
return frame.setLocal(index, value);
}
public Module getModule()
{
return _module;
}
public AnyClass getSelf()
{
return _self;
}
public String getPathinfo()
{
return _module.getPathinfo();
}
public int getLine()
{
return _line;
}
public void setLine(int line)
{
_line = line;
}
public void push(Any value)
{
if (_stack == null) {
_stack = new Any[4];
} if (_stackptr >= _stack.length) {
int len = _stack.length;
Any[] newstack = new Any[len + 4];
System.arraycopy(_stack, 0, newstack, 0, len);
_stack = newstack;
}
_stack[_stackptr++] = value;
}
public Any pop()
{
if (_stackptr > 0) {
return _stack[--_stackptr];
} else {
return Any.UNDEFINED;
}
}
public Any peek()
{
if (_stackptr > 0) {
return _stack[_stackptr-1];
} else {
return Any.UNDEFINED;
}
}
public Any peek(int pos)
{
if (_stackptr - pos > 0) {
return _stack[_stackptr - 1 - pos];
} else {
return Any.UNDEFINED;
}
}
public boolean isEscaped()
{
return _escaped;
}
public void setEscape(StackFrame escape)
{
_escape = escape;
}
public StackFrame getEscape()
{
return _escape;
}
public StackFrame getEscape(int depth)
{
StackFrame frame = _escape;
while(--depth > 0) {
frame = frame.getEscape();
}
return frame;
}
public Zone getZone()
{
Zone zone = _zone;
if (zone == null) {
return _zone = _module.getAddress().getZone();
} else {
return zone;
}
}
public void serialize(Serializer serializer) throws IOException
{
if (serializer.register(this)) {
return;
}
int n = _maxlocals;
serializer.write('[');
if (_escape != null) {
_escape.serialize(serializer);
} else {
serializer.write('n');
}
serializer.write(n);
serializer.write(';');
for(int i=0; i<n; i++) {
_locals[i].serialize(serializer);
}
serializer.write(']');
}
public static final StackFrame unserialize(Unserializer unserializer, Module module, AnyClass self, Function function) throws UnserializationException
{
Object obj = unserializer.consumeRegisteredIf();
if (obj != null) {
return (StackFrame)obj;
}
StackFrame frame = new StackFrame();
unserializer.register(frame);
unserializer.consume('[');
StackFrame parent = null;
if (unserializer.peek() == 'n') {
unserializer.consume('n');
} else {
parent = unserialize(unserializer, module, self, function);
}
int size = (int)unserializer.getLong();
frame.init(module, self, function, size, 0, true);
frame.setEscape(parent);
for(int i=0; i<size; i++) {
frame.setLocal(i, unserializer.unserialize());
}
unserializer.consume(']');
return frame;
}
}