oscript.util
Class StackFrame

java.lang.Object
  extended by oscript.util.StackFrame

public abstract class StackFrame
extends java.lang.Object

The "chain" of stack frames is used to track execution context of a particular thread and, when debugging is enabled, give the debugger a chance to run breakpoints.

Where possible, the head of the chain of stack frames is passed on the stack, but in cases where it cannot be, such as when control passes to java code and back, a hashtable is used to map the current thread to a StackFrame. To access the current stack frame, or create one if needed, use currentStackFrame().

While on the interface, the stack frame behaves as a chain of StackFrame objects, behind the scenes an array is used for the stack, and a fly-weight pattern is used for the stack frame objects. This way we (1) avoid extra memory allocations, and (2) can have different implementations of setLineNumber(oscript.data.Scope, int) depending on whether debugging is enabled or not. (Debugging is automatically enabled when a breakpoint is set.)

In order to maintain this allusion, calls to NodeEvaluator.evalNode(oscript.util.StackFrame, oscript.data.Scope) must go through the evalNode(oscript.NodeEvaluator, oscript.data.Scope) call-gate.

The stack frame object is intentionally not thread safe, since it is only accessed from a single thread context. Because of the use of the fly- weight pattern, a stack frame object no longer validly represents a stack frame that has exited, either by normally or via an exception. Because of this, any code that wishes to save a reference to a stack frame object must clone() it.

Because the StackFrame is only accessed from a single thread context, it can provide a lightweight mechanism to allocate storage for BasicScope objects. This can be used in cases where the scope object only exists on the stack, and is not held after the program enclosed by the scope has finished execution, ie. there is no function enclosed by the scope. For cases of an enclosed function, the scope storage must be allocated from the heap so that it can be valid at some point in the future when the enclosed function is potentially called.

Version:
1
Author:
Rob Clark (rob@ti.com)

Field Summary
protected  StackFrame debugStackFrame
          StackFrame to use whe debugging.
protected  short[] idx
          The current index, boxed in array so it can be shared between the two stack-frame instances (regular & debug)
protected  int[] lines
          The current line number at each stack frame.
protected  NodeEvaluator[] nes
          The node evaluator, which has file, and id info needed when filling in stack trace.
protected  StackFrame regularStackFrame
          StackFrame to use when not debugging.
protected  oscript.util.StackFrame.StackFrameBasicScope[] scopeLists
          The list of scopes allocated at the current frame, which should be recycled once the stack frame is released.
protected  Scope[] scopes
          The current scopes at each stack frame.
 
Method Summary
 BasicScope allocateBasicScope(Scope prev, SymbolTable smit)
          Allocate a scope from the stack.
 FunctionScope allocateFunctionScope(Function fxn, Scope prev, SymbolTable smit, MemberTable members)
          Allocate a fxn-scope from the stack.
 MemberTable allocateMemberTable(short sz)
          Allocate from the stack.
 java.lang.Object clone()
          Clone the stack frame, which is necessary in cases where you need to keep a reference to the stack frame (and it's parents) after the original stack frame has exited, such as to store in an exception.
static StackFrame currentStackFrame()
          Get the stack frame for the current thread.
static void dumpStack(java.io.OutputStream out)
          For debugging
static void dumpStack(java.io.Writer out)
           
 boolean equals(java.lang.Object obj)
           
 java.lang.Object evalNode(NodeEvaluator ne, Scope scope)
          Push a new stack frame onto the stack, and pass it to ne's evalNode(oscript.NodeEvaluator, oscript.data.Scope) method, returning the result.
 AbstractFile getFile()
          The file corresponding to the current stack frame.
 int getId()
          The function name for the current stack frame, if there is one, otherwise -1.
 int getLineNumber()
          The current line number in the current stack frame.
 Value getName()
          Convenience wrapper for getId(), mainly provided for the benefit of script code that probably doesn't want to know about ids, and just wants to think in terms of names.
 StackFrame getSafeCopy()
           
 Scope getScope()
          The current scope in the current line number.
 int hashCode()
           
 java.util.Iterator iterator()
          Return an iterator of stack frames, starting with the top of the stack, and iterating to root of stack.
static void log(java.lang.String str)
           
 void setLineNumber(int line)
          Called by node evaluator to store line number info, and to give the debugger a chance to see if we've hit a breakpoint.
 void setLineNumber(Scope scope, int line)
          Called by node evaluator to store line number info, and to give the debugger a chance to see if we've hit a breakpoint.
 java.lang.String toString()
          Convert to string, to print out a line in the stack-trace.
 
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

regularStackFrame

protected StackFrame regularStackFrame
StackFrame to use when not debugging. This one's setLineNumber(oscript.data.Scope, int) does not have extra checks for breakpoints for better performance. This should be treated as final.


debugStackFrame

protected StackFrame debugStackFrame
StackFrame to use whe debugging. This one's setLineNumber(oscript.data.Scope, int) does have extra checks for breakpoints, so breakpoints can work properly. This should be treated as final.


idx

protected final short[] idx
The current index, boxed in array so it can be shared between the two stack-frame instances (regular & debug)


nes

protected final NodeEvaluator[] nes
The node evaluator, which has file, and id info needed when filling in stack trace.


lines

protected final int[] lines
The current line number at each stack frame.


scopes

protected final Scope[] scopes
The current scopes at each stack frame.


scopeLists

protected final oscript.util.StackFrame.StackFrameBasicScope[] scopeLists
The list of scopes allocated at the current frame, which should be recycled once the stack frame is released.

Method Detail

currentStackFrame

public static StackFrame currentStackFrame()
Get the stack frame for the current thread. If one does not already exist, this will create a new one, otherwise it will return the current top of the stack.


evalNode

public final java.lang.Object evalNode(NodeEvaluator ne,
                                       Scope scope)
Push a new stack frame onto the stack, and pass it to ne's evalNode(oscript.NodeEvaluator, oscript.data.Scope) method, returning the result.

Parameters:
ne - the node-evaluator for the node to evaluate
scope - the scope to evalute in
Returns:
the result

setLineNumber

public void setLineNumber(Scope scope,
                          int line)
Called by node evaluator to store line number info, and to give the debugger a chance to see if we've hit a breakpoint.

Parameters:
scope - the current scope
line - the current line number

setLineNumber

public void setLineNumber(int line)
Called by node evaluator to store line number info, and to give the debugger a chance to see if we've hit a breakpoint. This method is used by the compiler in cases where the scope hasn't changed sinced last line number, to save a few instructions.

Parameters:
scope - the current scope
line - the current line number

allocateBasicScope

public final BasicScope allocateBasicScope(Scope prev,
                                           SymbolTable smit)
Allocate a scope from the stack. The basic-scope is freed automatically when the stack-frame is disposed


allocateFunctionScope

public final FunctionScope allocateFunctionScope(Function fxn,
                                                 Scope prev,
                                                 SymbolTable smit,
                                                 MemberTable members)
Allocate a fxn-scope from the stack. The fxn-scope must be freed by the caller.


allocateMemberTable

public final MemberTable allocateMemberTable(short sz)
Allocate from the stack.


getName

public Value getName()
Convenience wrapper for getId(), mainly provided for the benefit of script code that probably doesn't want to know about ids, and just wants to think in terms of names.


getId

public final int getId()
The function name for the current stack frame, if there is one, otherwise -1.


getFile

public final AbstractFile getFile()
The file corresponding to the current stack frame.


getLineNumber

public final int getLineNumber()
The current line number in the current stack frame.


getScope

public final Scope getScope()
The current scope in the current line number.


iterator

public java.util.Iterator iterator()
Return an iterator of stack frames, starting with the top of the stack, and iterating to root of stack.


getSafeCopy

public StackFrame getSafeCopy()

clone

public final java.lang.Object clone()
Clone the stack frame, which is necessary in cases where you need to keep a reference to the stack frame (and it's parents) after the original stack frame has exited, such as to store in an exception.

Overrides:
clone in class java.lang.Object

toString

public java.lang.String toString()
Convert to string, to print out a line in the stack-trace.

Overrides:
toString in class java.lang.Object

hashCode

public int hashCode()
Overrides:
hashCode in class java.lang.Object

equals

public boolean equals(java.lang.Object obj)
Overrides:
equals in class java.lang.Object

dumpStack

public static final void dumpStack(java.io.OutputStream out)
For debugging


dumpStack

public static final void dumpStack(java.io.Writer out)

log

public static final void log(java.lang.String str)