case JF: if (!JS.toBoolean(stack.pop())) pc += JS.toInt((JS)arg) - 1; break;
case JMP: pc += JS.toInt((JS)arg) - 1; break;
case POP: stack.pop(); break;
- case SWAP: {
- int depth = (arg == null ? 1 : JS.toInt((JS)arg));
- JS save = stack.elementAt(stack.size() - 1);
- for(int i=stack.size() - 1; i > stack.size() - 1 - depth; i--)
- stack.setElementAt(stack.elementAt(i-1), i);
- stack.setElementAt(save, stack.size() - depth - 1);
- break;
- }
+ case SWAP: stack.swap(); break;
case DUP: stack.push(stack.peek()); break;
case NEWSCOPE: scope = new JSScope(scope); break;
case OLDSCOPE: scope = scope.getParentScope(); break;
case PUSHKEYS: {
JS o = stack.peek();
- Enumeration e = o.keys();
- JSArray a = new JSArray();
- // FEATURE: Take advantage of the Enumeration, don't create a JSArray
- while(e.hasMoreElements()) a.addElement((JS)e.nextElement());
- stack.push(a);
+ stack.push(o == null ? null : o.keys());
break;
}
case BREAK:
case CONTINUE:
- while(stack.size() > 0) {
+ while(!stack.empty()) {
JS o = stack.pop();
if (o instanceof CallMarker) je("break or continue not within a loop");
if (o instanceof TryMarker) {
case RETURN: {
JS retval = stack.pop();
- while(stack.size() > 0) {
+ while(!stack.empty()) {
Object o = stack.pop();
if (o instanceof TryMarker) {
if(((TryMarker)o).finallyLoc < 0) continue;
Trap t = null;
TrapMarker tm = null;
if(target instanceof JSScope && key.jsequals(CASCADE)) {
- Object o=null;
- int i;
- for(i=stack.size()-1;i>=0;i--) if((o = stack.elementAt(i)) instanceof CallMarker) break;
- if(i==0) throw new Error("didn't find a call marker while doing cascade");
+ CallMarker o = stack.findCall();
if(o instanceof TrapMarker) {
tm = (TrapMarker) o;
target = tm.trapee;
Trap t = null;
TrapMarker tm = null;
if(target instanceof JSScope && key.jsequals(CASCADE)) {
- JS o=null;
- int i;
- for(i=stack.size()-1;i>=0;i--) if((o = stack.elementAt(i)) instanceof CallMarker) break;
- if(i==0) throw new Error("didn't find a call marker while doing cascade");
+ CallMarker o = stack.findCall();
if(o instanceof TrapMarker) {
tm = (TrapMarker) o;
target = tm.trapee;
}
case THROW:
- throw new JSExn(stack.pop(), stack, f, pc, scope);
+ throw new JSExn(stack.pop(), this);
/* FIXME GRAMMAR
case MAKE_GRAMMAR: {
if a handler is not found the exception is thrown
*/
void catchException(JSExn e) throws JSExn {
- while(stack.size() > 0) {
+ while(!stack.empty()) {
JS o = stack.pop();
if (o instanceof CatchMarker || o instanceof TryMarker) {
boolean inCatch = o instanceof CatchMarker;
private static final int MAX_STACK_SIZE = 512;
private JS[] stack = new JS[64];
private int sp = 0;
- public final void push(JS o) throws JSExn {
- if(sp == stack.length) grow();
- stack[sp++] = o;
- }
- public final JS peek() {
- if(sp == 0) throw new RuntimeException("Stack underflow");
- return stack[sp-1];
+
+ boolean empty() { return sp == 0; }
+ void push(JS o) throws JSExn { if(sp == stack.length) grow(); stack[sp++] = o; }
+ JS peek() { if(sp == 0) throw new RuntimeException("Stack underflow"); return stack[sp-1]; }
+ final JS pop() { if(sp == 0) throw new RuntimeException("Stack underflow"); return stack[--sp]; }
+ void swap() throws JSExn {
+ if(sp < 2) throw new JSExn("stack overflow");
+ JS tmp = stack[sp-2];
+ stack[sp-2] = stack[sp-1];
+ stack[sp-1] = tmp;
}
- public final JS pop() {
- if(sp == 0) throw new RuntimeException("Stack underflow");
- return stack[--sp];
+ CallMarker findCall() {
+ for(int i=sp-1;i>=0;i--) if(stack[i] instanceof CallMarker) return (CallMarker) stack[i];
+ return null;
}
- private void grow() throws JSExn {
+ void grow() throws JSExn {
if(stack.length >= MAX_STACK_SIZE) throw new JSExn("Stack overflow");
JS[] stack2 = new JS[stack.length * 2];
System.arraycopy(stack,0,stack2,0,stack.length);
- }
- public int size() { return sp; }
- public JS elementAt(int i) { return stack[i]; }
+ }
- // FIXME: Eliminate all uses of SWAP n>1 so we don't need this
- public void setElementAt(JS o, int i) { stack[i] = o; }
+ void backtrace(JSExn e) {
+ for(int i=sp-1;i>=0;i--) {
+ if (stack[i] instanceof CallMarker) {
+ CallMarker cm = (CallMarker)stack[i];
+ if(cm.f == null) break;
+ String s = cm.f.sourceName + ":" + cm.f.line[cm.pc-1];
+ if(cm instanceof Interpreter.TrapMarker)
+ s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).key) + ")";
+ e.addBacktrace(s);
+ }
+ }
+ }
}
}