try {
if (cx.paused) return null;
cx.bind();
- if (cx.tailCallFunction != null) {
- cx.stack.pop(); // discard actual return value
- cx.pc -= 2;
- cx.stack.push(new CallMarker(cx));
- cx.stack.push(cx.tailCallArgs);
- cx.currentCompiledFunction = cx.tailCallFunction;
- cx.tailCallFunction = null;
- cx.tailCallArgs = null;
- cx.scope = new FunctionScope("unknown", cx.currentCompiledFunction.parentScope);
- cx.pc = 0;
- }
if (cx.currentCompiledFunction == null) return cx.stack.pop();
if (cx.pc >= ((CompiledFunctionImpl)cx.currentCompiledFunction).size) return cx.stack.pop();
String label = null;
throw je("tried to put a value to the " + key + " property on a " + target.getClass().getName());
if (key == null)
throw je("tried to assign \"" + (val==null?"(null)":val.toString()) + "\" to the null key");
- ((JS)target).put(key, val);
+ // FIXME too many allocations here
+ TailCall tail = new TailCall();
+ ((JS)target).put(key, val, tail);
cx.stack.push(val);
+ if (tail.func != null) {
+ cx.stack.push(new CallMarker(cx));
+ cx.stack.push(tail.args);
+ cx.currentCompiledFunction = tail.func;
+ cx.scope = new CompiledFunctionImpl.FunctionScope("unknown", tail.func.parentScope);
+ cx.pc = -1;
+ break;
+ }
break;
}
ret = Internal.getFromPrimitive(o,v);
else if (o instanceof JS) {
ret = ((JS)o).get(v);
+ if (ret instanceof JS.TailCall) {
+ cx.stack.push(new CallMarker(cx));
+ cx.stack.push(((JS.TailCall)ret).args);
+ cx.currentCompiledFunction = ((JS.TailCall)ret).func;
+ cx.scope = new CompiledFunctionImpl.FunctionScope("unknown", ((JS.TailCall)ret).func.parentScope);
+ cx.pc = -1;
+ break;
+ }
} else
throw je("tried to get property " + v + " from a " + o.getClass().getName());
cx.stack.push(ret);
break;
} else {
o = ((JS)o).get(method);
+ if (o instanceof JS.TailCall) {
+ cx.stack.push(new CallMarker(cx));
+ cx.stack.push(((JS.TailCall)o).args);
+ cx.currentCompiledFunction = ((JS.TailCall)o).func;
+ cx.scope = new CompiledFunctionImpl.FunctionScope("unknown", ((JS.TailCall)o).func.parentScope);
+ cx.pc = -1;
+ break;
+ }
}
} else {
throw new JS.Exn("Tried to call a method on an object that isn't a JS object: " + o);
} else {
ret = ((JS.Callable)o).call(arguments);
+ if (ret instanceof JS.TailCall) {
+ cx.stack.push(new CallMarker(cx));
+ cx.stack.push(((JS.TailCall)ret).args);
+ cx.currentCompiledFunction = ((JS.TailCall)ret).func;
+ cx.scope = new CompiledFunctionImpl.FunctionScope("unknown", ((JS.TailCall)ret).func.parentScope);
+ cx.pc = -1;
+ break;
+ }
}
cx.stack.push(ret);
break;