package php.runtime.env; import php.runtime.Memory; import php.runtime.lang.IObject; public class CallStack { // call stack protected final static int CALL_STACK_INIT_SIZE = 255; protected int callStackTop = 0; protected int maxCallStackTop = -1; protected CallStackItem[] callStack = new CallStackItem[CALL_STACK_INIT_SIZE]; protected final Environment env; public CallStack(Environment env) { this.env = env; } public int getTop(){ return callStackTop; } public void push(CallStackItem stackItem) { if (callStackTop >= callStack.length){ CallStackItem[] newCallStack = new CallStackItem[callStack.length * 2]; System.arraycopy(callStack, 0, newCallStack, 0, callStack.length); callStack = newCallStack; } callStack[callStackTop++] = stackItem; maxCallStackTop = callStackTop; } public void push(TraceInfo trace, IObject self, Memory[] args, String function, String clazz, String staticClazz) { if (callStackTop >= callStack.length){ CallStackItem[] newCallStack = new CallStackItem[callStack.length * 2]; System.arraycopy(callStack, 0, newCallStack, 0, callStack.length); callStack = newCallStack; } if (callStackTop < maxCallStackTop) callStack[callStackTop++].setParameters(trace, self, args, function, clazz, staticClazz); else callStack[callStackTop++] = new CallStackItem(trace, self, args, function, clazz, staticClazz); maxCallStackTop = callStackTop; } public void push(IObject self, String method, Memory... args) { push(null, self, args, method, self.getReflection().getName(), null); } public void push(TraceInfo trace, IObject self, String method, Memory... args) { push(trace, self, args, method, self.getReflection().getName(), null); } public void pop() { try { callStack[--callStackTop].clear(); // clear for GC } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalThreadStateException(); } } public CallStackItem peekCall(int depth) { if (callStackTop - depth > 0) { return callStack[callStackTop - depth - 1]; } else { return null; } } public CallStack getSnapshotAsCallStack() { CallStack stack = new CallStack(env); stack.callStack = new CallStackItem[callStack.length]; System.arraycopy(getSnapshot(), 0, stack.callStack, 0, callStackTop); stack.callStackTop = callStackTop; stack.maxCallStackTop = maxCallStackTop; return stack; } public CallStackItem[] getSnapshot(){ if (callStackTop < 0) { return new CallStackItem[] { }; } CallStackItem[] result = new CallStackItem[callStackTop]; int i = 0; for(CallStackItem el : callStack){ if (i == callStackTop) break; result[i] = new CallStackItem(el); i++; } return result; } public TraceInfo trace(){ if (callStackTop <= 0) return TraceInfo.UNKNOWN; return peekCall(0).trace; } public TraceInfo trace(int systemOffsetStackTrace){ return new TraceInfo(Thread.currentThread().getStackTrace()[systemOffsetStackTrace]); } }